]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPMrootDomain.cpp
2aec3e5c37ebf4a426e354cf8883181d85f3a9ea
[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 "IOKitKernelInternal.h"
58 #if HIBERNATION
59 #include <IOKit/IOHibernatePrivate.h>
60 #endif /* HIBERNATION */
61 #include <console/video_console.h>
62 #include <sys/syslog.h>
63 #include <sys/sysctl.h>
64 #include <sys/vnode.h>
65 #include <sys/vnode_internal.h>
66 #include <sys/fcntl.h>
67 #include <os/log.h>
68 #include <pexpert/protos.h>
69 #include <AssertMacros.h>
70
71 #include <sys/time.h>
72 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
73 #include "IOServicePMPrivate.h"
74
75 #include <libkern/zlib.h>
76 #include <os/cpp_util.h>
77 #include <libkern/c++/OSBoundedArrayRef.h>
78
79 __BEGIN_DECLS
80 #include <mach/shared_region.h>
81 #include <kern/clock.h>
82 __END_DECLS
83
84 #if defined(__i386__) || defined(__x86_64__)
85 __BEGIN_DECLS
86 #include "IOPMrootDomainInternal.h"
87 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
88 __END_DECLS
89 #endif
90
91 #define kIOPMrootDomainClass "IOPMrootDomain"
92 #define LOG_PREFIX "PMRD: "
93
94
95 #define MSG(x...) \
96 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
97
98 #define LOG(x...) \
99 do { kprintf(LOG_PREFIX x); } while (false)
100
101 #if DEVELOPMENT || DEBUG
102 #define DEBUG_LOG(x...) do { \
103 if (kIOLogPMRootDomain & gIOKitDebug) \
104 kprintf(LOG_PREFIX x); \
105 os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
106 } while (false)
107 #else
108 #define DEBUG_LOG(x...)
109 #endif
110
111 #define DLOG(x...) do { \
112 if (kIOLogPMRootDomain & gIOKitDebug) \
113 kprintf(LOG_PREFIX x); \
114 else \
115 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
116 } while (false)
117
118 #define DMSG(x...) do { \
119 if (kIOLogPMRootDomain & gIOKitDebug) { \
120 kprintf(LOG_PREFIX x); \
121 } \
122 } while (false)
123
124
125 #define _LOG(x...)
126
127 #define CHECK_THREAD_CONTEXT
128 #ifdef CHECK_THREAD_CONTEXT
129 static IOWorkLoop * gIOPMWorkLoop = NULL;
130 #define ASSERT_GATED() \
131 do { \
132 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
133 panic("RootDomain: not inside PM gate"); \
134 } \
135 } while(false)
136 #else
137 #define ASSERT_GATED()
138 #endif /* CHECK_THREAD_CONTEXT */
139
140 #define CAP_LOSS(c) \
141 (((_pendingCapability & (c)) == 0) && \
142 ((_currentCapability & (c)) != 0))
143
144 #define CAP_GAIN(c) \
145 (((_currentCapability & (c)) == 0) && \
146 ((_pendingCapability & (c)) != 0))
147
148 #define CAP_CHANGE(c) \
149 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
150
151 #define CAP_CURRENT(c) \
152 ((_currentCapability & (c)) != 0)
153
154 #define CAP_HIGHEST(c) \
155 ((_highestCapability & (c)) != 0)
156
157 #define CAP_PENDING(c) \
158 ((_pendingCapability & (c)) != 0)
159
160 // rdar://problem/9157444
161 #if defined(__i386__) || defined(__x86_64__)
162 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 20
163 #endif
164
165 // Event types for IOPMPowerStateQueue::submitPowerEvent()
166 enum {
167 kPowerEventFeatureChanged = 1, // 1
168 kPowerEventReceivedPowerNotification, // 2
169 kPowerEventSystemBootCompleted, // 3
170 kPowerEventSystemShutdown, // 4
171 kPowerEventUserDisabledSleep, // 5
172 kPowerEventRegisterSystemCapabilityClient, // 6
173 kPowerEventRegisterKernelCapabilityClient, // 7
174 kPowerEventPolicyStimulus, // 8
175 kPowerEventAssertionCreate, // 9
176 kPowerEventAssertionRelease, // 10
177 kPowerEventAssertionSetLevel, // 11
178 kPowerEventQueueSleepWakeUUID, // 12
179 kPowerEventPublishSleepWakeUUID, // 13
180 kPowerEventSetDisplayPowerOn, // 14
181 kPowerEventPublishWakeType, // 15
182 kPowerEventAOTEvaluate // 16
183 };
184
185 // For evaluatePolicy()
186 // List of stimuli that affects the root domain policy.
187 enum {
188 kStimulusDisplayWranglerSleep, // 0
189 kStimulusDisplayWranglerWake, // 1
190 kStimulusAggressivenessChanged, // 2
191 kStimulusDemandSystemSleep, // 3
192 kStimulusAllowSystemSleepChanged, // 4
193 kStimulusDarkWakeActivityTickle, // 5
194 kStimulusDarkWakeEntry, // 6
195 kStimulusDarkWakeReentry, // 7
196 kStimulusDarkWakeEvaluate, // 8
197 kStimulusNoIdleSleepPreventers, // 9
198 kStimulusEnterUserActiveState, // 10
199 kStimulusLeaveUserActiveState // 11
200 };
201
202 // Internal power state change reasons
203 // Must be less than kIOPMSleepReasonClamshell=101
204 enum {
205 kCPSReasonNone = 0, // 0
206 kCPSReasonInit, // 1
207 kCPSReasonWake, // 2
208 kCPSReasonIdleSleepPrevent, // 3
209 kCPSReasonIdleSleepAllow, // 4
210 kCPSReasonPowerOverride, // 5
211 kCPSReasonPowerDownCancel, // 6
212 kCPSReasonAOTExit, // 7
213 kCPSReasonAdjustPowerState, // 8
214 kCPSReasonDarkWakeCannotSleep, // 9
215 kCPSReasonIdleSleepEnabled, // 10
216 kCPSReasonEvaluatePolicy, // 11
217 kCPSReasonSustainFullWake, // 12
218 kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1)
219 };
220
221 extern "C" {
222 IOReturn OSKextSystemSleepOrWake( UInt32 );
223 }
224 extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
225 extern "C" addr64_t kvtophys(vm_offset_t va);
226 extern "C" boolean_t kdp_has_polled_corefile();
227
228 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
229 static void notifySystemShutdown( IOService * root, uint32_t messageType );
230 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
231 static void pmEventTimeStamp(uint64_t *recordTS);
232 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
233 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
234 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address);
235
236 static int IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt);
237 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
238 #define YMDTF "%04d/%02d/%d %02d:%02d:%02d"
239 #define YMDT(cal) ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
240
241 // "IOPMSetSleepSupported" callPlatformFunction name
242 static OSSharedPtr<const OSSymbol> sleepSupportedPEFunction;
243 static OSSharedPtr<const OSSymbol> sleepMessagePEFunction;
244 static OSSharedPtr<const OSSymbol> gIOPMWakeTypeUserKey;
245
246 static OSSharedPtr<const OSSymbol> gIOPMPSExternalConnectedKey;
247 static OSSharedPtr<const OSSymbol> gIOPMPSExternalChargeCapableKey;
248 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryInstalledKey;
249 static OSSharedPtr<const OSSymbol> gIOPMPSIsChargingKey;
250 static OSSharedPtr<const OSSymbol> gIOPMPSAtWarnLevelKey;
251 static OSSharedPtr<const OSSymbol> gIOPMPSAtCriticalLevelKey;
252 static OSSharedPtr<const OSSymbol> gIOPMPSCurrentCapacityKey;
253 static OSSharedPtr<const OSSymbol> gIOPMPSMaxCapacityKey;
254 static OSSharedPtr<const OSSymbol> gIOPMPSDesignCapacityKey;
255 static OSSharedPtr<const OSSymbol> gIOPMPSTimeRemainingKey;
256 static OSSharedPtr<const OSSymbol> gIOPMPSAmperageKey;
257 static OSSharedPtr<const OSSymbol> gIOPMPSVoltageKey;
258 static OSSharedPtr<const OSSymbol> gIOPMPSCycleCountKey;
259 static OSSharedPtr<const OSSymbol> gIOPMPSMaxErrKey;
260 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterInfoKey;
261 static OSSharedPtr<const OSSymbol> gIOPMPSLocationKey;
262 static OSSharedPtr<const OSSymbol> gIOPMPSErrorConditionKey;
263 static OSSharedPtr<const OSSymbol> gIOPMPSManufacturerKey;
264 static OSSharedPtr<const OSSymbol> gIOPMPSManufactureDateKey;
265 static OSSharedPtr<const OSSymbol> gIOPMPSModelKey;
266 static OSSharedPtr<const OSSymbol> gIOPMPSSerialKey;
267 static OSSharedPtr<const OSSymbol> gIOPMPSLegacyBatteryInfoKey;
268 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryHealthKey;
269 static OSSharedPtr<const OSSymbol> gIOPMPSHealthConfidenceKey;
270 static OSSharedPtr<const OSSymbol> gIOPMPSCapacityEstimatedKey;
271 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryChargeStatusKey;
272 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryTemperatureKey;
273 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsKey;
274 static OSSharedPtr<const OSSymbol> gIOPMPSChargerConfigurationKey;
275 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsIDKey;
276 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsWattsKey;
277 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsRevisionKey;
278 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSerialNumberKey;
279 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsFamilyKey;
280 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsAmperageKey;
281 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsDescriptionKey;
282 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsPMUConfigurationKey;
283 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSourceIDKey;
284 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsErrorFlagsKey;
285 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSharedSourceKey;
286 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsCloakedKey;
287 static OSSharedPtr<const OSSymbol> gIOPMPSInvalidWakeSecondsKey;
288 static OSSharedPtr<const OSSymbol> gIOPMPSPostChargeWaitSecondsKey;
289 static OSSharedPtr<const OSSymbol> gIOPMPSPostDishargeWaitSecondsKey;
290
291 #define kIOSleepSupportedKey "IOSleepSupported"
292 #define kIOPMSystemCapabilitiesKey "System Capabilities"
293 #define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
294
295 #define kIORequestWranglerIdleKey "IORequestIdle"
296 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
297
298 #define kIOSleepWakeFailureString "SleepWakeFailureString"
299 #define kIOEFIBootRomFailureKey "wake-failure"
300 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic"
301
302 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
303 | kIOPMSupportedOnBatt \
304 | kIOPMSupportedOnUPS)
305
306 #define kLocalEvalClamshellCommand (1 << 15)
307 #define kIdleSleepRetryInterval (3 * 60)
308
309 #define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID)
310
311 enum {
312 kWranglerPowerStateMin = 0,
313 kWranglerPowerStateSleep = 2,
314 kWranglerPowerStateDim = 3,
315 kWranglerPowerStateMax = 4
316 };
317
318 enum {
319 OFF_STATE = 0,
320 RESTART_STATE = 1,
321 SLEEP_STATE = 2,
322 AOT_STATE = 3,
323 ON_STATE = 4,
324 NUM_POWER_STATES
325 };
326
327 const char *
328 getPowerStateString( uint32_t state )
329 {
330 #define POWER_STATE(x) {(uint32_t) x, #x}
331
332 static const IONamedValue powerStates[] = {
333 POWER_STATE( OFF_STATE ),
334 POWER_STATE( RESTART_STATE ),
335 POWER_STATE( SLEEP_STATE ),
336 POWER_STATE( AOT_STATE ),
337 POWER_STATE( ON_STATE ),
338 { 0, NULL }
339 };
340 return IOFindNameForValue(state, powerStates);
341 }
342
343 #define ON_POWER kIOPMPowerOn
344 #define RESTART_POWER kIOPMRestart
345 #define SLEEP_POWER kIOPMAuxPowerOn
346
347 static IOPMPowerState
348 ourPowerStates[NUM_POWER_STATES] =
349 {
350 { .version = 1,
351 .capabilityFlags = 0,
352 .outputPowerCharacter = 0,
353 .inputPowerRequirement = 0 },
354 { .version = 1,
355 .capabilityFlags = kIOPMRestartCapability,
356 .outputPowerCharacter = kIOPMRestart,
357 .inputPowerRequirement = RESTART_POWER },
358 { .version = 1,
359 .capabilityFlags = kIOPMSleepCapability,
360 .outputPowerCharacter = kIOPMSleep,
361 .inputPowerRequirement = SLEEP_POWER },
362 { .version = 1,
363 .capabilityFlags = kIOPMAOTCapability,
364 .outputPowerCharacter = kIOPMAOTPower,
365 .inputPowerRequirement = ON_POWER },
366 { .version = 1,
367 .capabilityFlags = kIOPMPowerOn,
368 .outputPowerCharacter = kIOPMPowerOn,
369 .inputPowerRequirement = ON_POWER },
370 };
371
372 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
373 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
374 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
375 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
376 #define kIOPMRootDomainWakeTypeUser "User"
377 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
378 #define kIOPMRootDomainWakeTypeNetwork "Network"
379 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
380 #define kIOPMRootDomainWakeTypeNotification "Notification"
381 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
382
383 // Special interest that entitles the interested client from receiving
384 // all system messages. Only used by powerd.
385 //
386 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
387
388 // Entitlement required for root domain clients
389 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
390
391 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
392 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
393
394 /*
395 * Aggressiveness
396 */
397 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
398 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
399
400 #define kAggressivesMinValue 1
401
402 const char *
403 getAggressivenessTypeString( uint32_t type )
404 {
405 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
406
407 static const IONamedValue aggressivenessTypes[] = {
408 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ),
409 AGGRESSIVENESS_TYPE( kPMMinutesToDim ),
410 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ),
411 AGGRESSIVENESS_TYPE( kPMMinutesToSleep ),
412 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ),
413 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ),
414 AGGRESSIVENESS_TYPE( kPMPowerSource),
415 AGGRESSIVENESS_TYPE( kPMMotionSensor ),
416 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ),
417 { 0, NULL }
418 };
419 return IOFindNameForValue(type, aggressivenessTypes);
420 }
421
422 enum {
423 kAggressivesStateBusy = 0x01,
424 kAggressivesStateQuickSpindown = 0x02
425 };
426
427 struct AggressivesRecord {
428 uint32_t flags;
429 uint32_t type;
430 uint32_t value;
431 };
432
433 struct AggressivesRequest {
434 queue_chain_t chain;
435 uint32_t options;
436 uint32_t dataType;
437 union {
438 OSSharedPtr<IOService> service;
439 AggressivesRecord record;
440 } data;
441 };
442
443 enum {
444 kAggressivesRequestTypeService = 1,
445 kAggressivesRequestTypeRecord
446 };
447
448 enum {
449 kAggressivesOptionSynchronous = 0x00000001,
450 kAggressivesOptionQuickSpindownEnable = 0x00000100,
451 kAggressivesOptionQuickSpindownDisable = 0x00000200,
452 kAggressivesOptionQuickSpindownMask = 0x00000300
453 };
454
455 enum {
456 kAggressivesRecordFlagModified = 0x00000001,
457 kAggressivesRecordFlagMinValue = 0x00000002
458 };
459
460 // System Sleep Preventers
461
462 enum {
463 kPMUserDisabledAllSleep = 1,
464 kPMSystemRestartBootingInProgress,
465 kPMConfigPreventSystemSleep,
466 kPMChildPreventSystemSleep,
467 kPMCPUAssertion,
468 kPMPCIUnsupported,
469 };
470
471 const char *
472 getSystemSleepPreventerString( uint32_t preventer )
473 {
474 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
475 static const IONamedValue systemSleepPreventers[] = {
476 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ),
477 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ),
478 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ),
479 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ),
480 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ),
481 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ),
482 { 0, NULL }
483 };
484 return IOFindNameForValue(preventer, systemSleepPreventers);
485 }
486
487 // gDarkWakeFlags
488 enum {
489 kDarkWakeFlagPromotionNone = 0x0000,
490 kDarkWakeFlagPromotionEarly = 0x0001, // promote before gfx clamp
491 kDarkWakeFlagPromotionLate = 0x0002, // promote after gfx clamp
492 kDarkWakeFlagPromotionMask = 0x0003,
493 kDarkWakeFlagAlarmIsDark = 0x0100,
494 kDarkWakeFlagAudioNotSuppressed = 0x0200,
495 kDarkWakeFlagUserWakeWorkaround = 0x1000
496 };
497
498 // gClamshellFlags
499 // The workaround for 9157444 is enabled at compile time using the
500 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below.
501 enum {
502 kClamshell_WAR_38378787 = 0x00000001,
503 kClamshell_WAR_47715679 = 0x00000002,
504 kClamshell_WAR_58009435 = 0x00000004
505 };
506
507 // acceptSystemWakeEvents()
508 enum {
509 kAcceptSystemWakeEvents_Disable = 0,
510 kAcceptSystemWakeEvents_Enable,
511 kAcceptSystemWakeEvents_Reenable
512 };
513
514 static IOPMrootDomain * gRootDomain;
515 static IORootParent * gPatriarch;
516 static IONotifier * gSysPowerDownNotifier = NULL;
517 static UInt32 gSleepOrShutdownPending = 0;
518 static UInt32 gWillShutdown = 0;
519 static UInt32 gPagingOff = 0;
520 static UInt32 gSleepWakeUUIDIsSet = false;
521 static uint32_t gAggressivesState = 0;
522 static uint32_t gHaltTimeMaxLog;
523 static uint32_t gHaltTimeMaxPanic;
524 IOLock * gHaltLogLock;
525 static char * gHaltLog;
526 enum { kHaltLogSize = 2048 };
527 static size_t gHaltLogPos;
528 static uint64_t gHaltStartTime;
529 static char gKextNameBuf[64];
530 static size_t gKextNamePos;
531 static bool gKextNameEnd;
532
533 uuid_string_t bootsessionuuid_string;
534
535 #if defined(XNU_TARGET_OS_OSX)
536 #if DISPLAY_WRANGLER_PRESENT
537 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionNone;
538 #elif CONFIG_ARROW
539 // Enable temporary full wake promotion workarounds
540 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
541 #else
542 // Enable full wake promotion workarounds
543 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
544 #endif
545 #else /* !defined(XNU_TARGET_OS_OSX) */
546 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionEarly;
547 #endif /* !defined(XNU_TARGET_OS_OSX) */
548
549 static uint32_t gNoIdleFlag = 0;
550 static uint32_t gSwdPanic = 1;
551 static uint32_t gSwdSleepTimeout = 0;
552 static uint32_t gSwdWakeTimeout = 0;
553 static uint32_t gSwdSleepWakeTimeout = 0;
554 static PMStatsStruct gPMStats;
555 #if DEVELOPMENT || DEBUG
556 static uint32_t swd_panic_phase;
557 #endif
558
559 static uint32_t gClamshellFlags = 0
560 #if defined(__i386__) || defined(__x86_64__)
561 | kClamshell_WAR_58009435
562 #endif
563 ;
564
565 #if HIBERNATION
566
567 #if defined(__arm64__)
568 static IOReturn
569 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params)
570 {
571 uint32_t sleepType = kIOPMSleepTypeDeepIdle;
572
573 assert(vars->signature == kIOPMSystemSleepPolicySignature);
574 assert(vars->version == kIOPMSystemSleepPolicyVersion);
575
576 // Hibernation enabled and either user forced hibernate or low battery sleep
577 if ((vars->hibernateMode & kIOHibernateModeOn) &&
578 (((vars->hibernateMode & kIOHibernateModeSleep) == 0) ||
579 (vars->sleepFactors & kIOPMSleepFactorBatteryLow))) {
580 sleepType = kIOPMSleepTypeHibernate;
581 }
582 params->version = kIOPMSystemSleepParametersVersion;
583 params->sleepType = sleepType;
584 return kIOReturnSuccess;
585 }
586 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = &defaultSleepPolicyHandler;
587 #else /* defined(__arm64__) */
588 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = NULL;
589 #endif /* defined(__arm64__) */
590
591 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
592 static void * gSleepPolicyTarget;
593 #endif
594
595 struct timeval gIOLastSleepTime;
596 struct timeval gIOLastWakeTime;
597 AbsoluteTime gIOLastWakeAbsTime;
598 AbsoluteTime gIOLastSleepAbsTime;
599
600 struct timeval gIOLastUserSleepTime;
601
602 static char gWakeReasonString[128];
603 static char gBootReasonString[80];
604 static char gShutdownReasonString[80];
605 static bool gWakeReasonSysctlRegistered = false;
606 static bool gBootReasonSysctlRegistered = false;
607 static bool gShutdownReasonSysctlRegistered = false;
608 static AbsoluteTime gUserActiveAbsTime;
609 static AbsoluteTime gUserInactiveAbsTime;
610
611 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
612 static bool gSpinDumpBufferFull = false;
613 #endif
614
615 z_stream swd_zs;
616 vm_offset_t swd_zs_zmem;
617 //size_t swd_zs_zsize;
618 size_t swd_zs_zoffset;
619 #if defined(__i386__) || defined(__x86_64__)
620 IOCPU *currentShutdownTarget = NULL;
621 #endif
622
623 static unsigned int gPMHaltBusyCount;
624 static unsigned int gPMHaltIdleCount;
625 static int gPMHaltDepth;
626 static uint32_t gPMHaltMessageType;
627 static IOLock * gPMHaltLock = NULL;
628 static OSSharedPtr<OSArray> gPMHaltArray;
629 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey;
630 static bool gPMQuiesced;
631
632 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
633 #define kCPUUnknownIndex 9999999
634 enum {
635 kInformAC = 0,
636 kInformLid = 1,
637 kInformableCount = 2
638 };
639
640 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut;
641 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel;
642 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow;
643 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt;
644 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow;
645
646 #define kBadPMFeatureID 0
647
648 /*
649 * PMSettingHandle
650 * Opaque handle passed to clients of registerPMSettingController()
651 */
652 class PMSettingHandle : public OSObject
653 {
654 OSDeclareFinalStructors( PMSettingHandle );
655 friend class PMSettingObject;
656
657 private:
658 PMSettingObject *pmso;
659 void free(void) APPLE_KEXT_OVERRIDE;
660 };
661
662 /*
663 * PMSettingObject
664 * Internal object to track each PM setting controller
665 */
666 class PMSettingObject : public OSObject
667 {
668 OSDeclareFinalStructors( PMSettingObject );
669 friend class IOPMrootDomain;
670
671 private:
672 queue_head_t calloutQueue;
673 thread_t waitThread;
674 IOPMrootDomain *parent;
675 PMSettingHandle *pmsh;
676 IOPMSettingControllerCallback func;
677 OSObject *target;
678 uintptr_t refcon;
679 uint32_t *publishedFeatureID;
680 uint32_t settingCount;
681 bool disabled;
682
683 void free(void) APPLE_KEXT_OVERRIDE;
684
685 public:
686 static PMSettingObject *pmSettingObject(
687 IOPMrootDomain *parent_arg,
688 IOPMSettingControllerCallback handler_arg,
689 OSObject *target_arg,
690 uintptr_t refcon_arg,
691 uint32_t supportedPowerSources,
692 const OSSymbol *settings[],
693 OSObject **handle_obj);
694
695 IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
696 void clientHandleFreed(void);
697 };
698
699 struct PMSettingCallEntry {
700 queue_chain_t link;
701 thread_t thread;
702 };
703
704 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
705 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
706 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
707 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
708
709 /*
710 * PMTraceWorker
711 * Internal helper object for logging trace points to RTC
712 * IOPMrootDomain and only IOPMrootDomain should instantiate
713 * exactly one of these.
714 */
715
716 typedef void (*IOPMTracePointHandler)(
717 void * target, uint32_t code, uint32_t data );
718
719 class PMTraceWorker : public OSObject
720 {
721 OSDeclareDefaultStructors(PMTraceWorker);
722 public:
723 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
724
725 static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * );
726 void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
727 void tracePoint(uint8_t phase);
728 void traceDetail(uint32_t detail);
729 void traceComponentWakeProgress(uint32_t component, uint32_t data);
730 int recordTopLevelPCIDevice(IOService *);
731 void RTC_TRACE(void);
732 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
733
734 IOPMTracePointHandler tracePointHandler;
735 void * tracePointTarget;
736 uint64_t getPMStatusCode();
737 uint8_t getTracePhase();
738 uint32_t getTraceData();
739 private:
740 IOPMrootDomain *owner;
741 IOLock *pmTraceWorkerLock;
742 OSSharedPtr<OSArray> pciDeviceBitMappings;
743
744 uint8_t addedToRegistry;
745 uint8_t tracePhase;
746 uint32_t traceData32;
747 uint8_t loginWindowData;
748 uint8_t coreDisplayData;
749 uint8_t coreGraphicsData;
750 };
751
752 /*
753 * PMAssertionsTracker
754 * Tracks kernel and user space PM assertions
755 */
756 class PMAssertionsTracker : public OSObject
757 {
758 OSDeclareFinalStructors(PMAssertionsTracker);
759 public:
760 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * );
761
762 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
763 IOReturn releaseAssertion(IOPMDriverAssertionID);
764 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
765 IOReturn setUserAssertionLevels(IOPMDriverAssertionType);
766
767 OSSharedPtr<OSArray> copyAssertionsArray(void);
768 IOPMDriverAssertionType getActivatedAssertions(void);
769 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType);
770
771 IOReturn handleCreateAssertion(OSData *);
772 IOReturn handleReleaseAssertion(IOPMDriverAssertionID);
773 IOReturn handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
774 IOReturn handleSetUserAssertionLevels(void * arg0);
775 void publishProperties(void);
776 void reportCPUBitAccounting(void);
777
778 private:
779 /*
780 * this should be treated as POD, as it's byte-copied around
781 * and we cannot rely on d'tor firing at the right time
782 */
783 typedef struct {
784 IOPMDriverAssertionID id;
785 IOPMDriverAssertionType assertionBits;
786 uint64_t createdTime;
787 uint64_t modifiedTime;
788 const OSSymbol *ownerString;
789 IOService *ownerService;
790 uint64_t registryEntryID;
791 IOPMDriverAssertionLevel level;
792 uint64_t assertCPUStartTime;
793 uint64_t assertCPUDuration;
794 } PMAssertStruct;
795
796 uint32_t tabulateProducerCount;
797 uint32_t tabulateConsumerCount;
798
799 uint64_t maxAssertCPUDuration;
800 uint64_t maxAssertCPUEntryId;
801
802 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *);
803 void tabulate(void);
804 void updateCPUBitAccounting(PMAssertStruct * assertStruct);
805
806 IOPMrootDomain *owner;
807 OSSharedPtr<OSArray> assertionsArray;
808 IOLock *assertionsArrayLock;
809 IOPMDriverAssertionID issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
810 IOPMDriverAssertionType assertionsKernel;
811 IOPMDriverAssertionType assertionsUser;
812 IOPMDriverAssertionType assertionsCombined;
813 };
814
815 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
816
817 /*
818 * PMHaltWorker
819 * Internal helper object for Shutdown/Restart notifications.
820 */
821 #define kPMHaltMaxWorkers 8
822 #define kPMHaltTimeoutMS 100
823
824 class PMHaltWorker : public OSObject
825 {
826 OSDeclareFinalStructors( PMHaltWorker );
827
828 public:
829 IOService * service;// service being worked on
830 AbsoluteTime startTime; // time when work started
831 int depth; // work on nubs at this PM-tree depth
832 int visits; // number of nodes visited (debug)
833 IOLock * lock;
834 bool timeout;// service took too long
835
836 static PMHaltWorker * worker( void );
837 static void main( void * arg, wait_result_t waitResult );
838 static void work( PMHaltWorker * me );
839 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
840 virtual void free( void ) APPLE_KEXT_OVERRIDE;
841 };
842
843 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
844
845
846 #define super IOService
847 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
848
849 boolean_t
850 IOPMRootDomainGetWillShutdown(void)
851 {
852 return gWillShutdown != 0;
853 }
854
855 static void
856 IOPMRootDomainWillShutdown(void)
857 {
858 if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
859 IOService::willShutdown();
860 for (int i = 0; i < 100; i++) {
861 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
862 break;
863 }
864 IOSleep( 100 );
865 }
866 }
867 }
868
869 extern "C" IONotifier *
870 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
871 {
872 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
873 }
874
875 extern "C" IONotifier *
876 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
877 {
878 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
879 }
880
881 extern "C" IOReturn
882 acknowledgeSleepWakeNotification(void * PMrefcon)
883 {
884 return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
885 }
886
887 extern "C" IOReturn
888 vetoSleepWakeNotification(void * PMrefcon)
889 {
890 return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
891 }
892
893 extern "C" IOReturn
894 rootDomainRestart( void )
895 {
896 return gRootDomain->restartSystem();
897 }
898
899 extern "C" IOReturn
900 rootDomainShutdown( void )
901 {
902 return gRootDomain->shutdownSystem();
903 }
904
905 static void
906 halt_log_putc(char c)
907 {
908 if (gHaltLogPos >= (kHaltLogSize - 2)) {
909 return;
910 }
911 gHaltLog[gHaltLogPos++] = c;
912 }
913
914 extern "C" void
915 _doprnt_log(const char *fmt,
916 va_list *argp,
917 void (*putc)(char),
918 int radix);
919
920 static int
921 halt_log(const char *fmt, ...)
922 {
923 va_list listp;
924
925 va_start(listp, fmt);
926 _doprnt_log(fmt, &listp, &halt_log_putc, 16);
927 va_end(listp);
928
929 return 0;
930 }
931
932 extern "C" void
933 halt_log_enter(const char * what, const void * pc, uint64_t time)
934 {
935 uint64_t nano, millis;
936
937 if (!gHaltLog) {
938 return;
939 }
940 absolutetime_to_nanoseconds(time, &nano);
941 millis = nano / NSEC_PER_MSEC;
942 if (millis < 100) {
943 return;
944 }
945
946 IOLockLock(gHaltLogLock);
947 if (pc) {
948 halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
949 OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
950 OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
951 } else {
952 halt_log("%s: %qd ms\n", what, millis);
953 }
954
955 gHaltLog[gHaltLogPos] = 0;
956 IOLockUnlock(gHaltLogLock);
957 }
958
959 extern uint32_t gFSState;
960
961 extern "C" void
962 IOSystemShutdownNotification(int stage)
963 {
964 uint64_t startTime;
965
966 if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
967 #if defined(XNU_TARGET_OS_OSX)
968 uint64_t nano, millis;
969 startTime = mach_absolute_time();
970 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
971 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
972 millis = nano / NSEC_PER_MSEC;
973 if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
974 printf("waitQuiet() for unmount %qd ms\n", millis);
975 }
976 #endif /* defined(XNU_TARGET_OS_OSX) */
977 return;
978 }
979
980 assert(kIOSystemShutdownNotificationStageProcessExit == stage);
981
982 IOLockLock(gHaltLogLock);
983 if (!gHaltLog) {
984 gHaltLog = IONew(char, kHaltLogSize);
985 gHaltStartTime = mach_absolute_time();
986 if (gHaltLog) {
987 halt_log_putc('\n');
988 }
989 }
990 IOLockUnlock(gHaltLogLock);
991
992 startTime = mach_absolute_time();
993 IOPMRootDomainWillShutdown();
994 halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
995 #if HIBERNATION
996 startTime = mach_absolute_time();
997 IOHibernateSystemPostWake(true);
998 halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
999 #endif
1000 if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1001 gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1002 }
1003 }
1004
1005
1006 extern "C" int sync_internal(void);
1007
1008 /*
1009 * A device is always in the highest power state which satisfies its driver,
1010 * its policy-maker, and any power children it has, but within the constraint
1011 * of the power state provided by its parent. The driver expresses its desire by
1012 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
1013 * changePowerStateToPriv(), and the children express their desires by calling
1014 * requestPowerDomainState().
1015 *
1016 * The Root Power Domain owns the policy for idle and demand sleep for the system.
1017 * It is a power-managed IOService just like the others in the system.
1018 * It implements several power states which map to what we see as Sleep and On.
1019 *
1020 * The sleep policy is as follows:
1021 * 1. Sleep is prevented if the case is open so that nobody will think the machine
1022 * is off and plug/unplug cards.
1023 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1024 * 3. System cannot Sleep if some object in the tree is in a power state marked
1025 * kIOPMPreventSystemSleep.
1026 *
1027 * These three conditions are enforced using the "driver clamp" by calling
1028 * changePowerStateTo(). For example, if the case is opened,
1029 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
1030 * of the desires of the children of the root or the state of the other clamp.
1031 *
1032 * Demand Sleep is initiated by pressing the front panel power button, closing
1033 * the clamshell, or selecting the menu item. In this case the root's parent
1034 * actually initiates the power state change so that the root domain has no
1035 * choice and does not give applications the opportunity to veto the change.
1036 *
1037 * Idle Sleep occurs if no objects in the tree are in a state marked
1038 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
1039 * the root on, so it sets the "policy-maker clamp" by calling
1040 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1041 * This timer is set for the difference between the sleep timeout slider and the
1042 * display dim timeout slider. When the timer expires, it releases its clamp and
1043 * now nothing is holding it awake, so it falls asleep.
1044 *
1045 * Demand sleep is prevented when the system is booting. When preferences are
1046 * transmitted by the loginwindow at the end of boot, a flag is cleared,
1047 * and this allows subsequent Demand Sleep.
1048 */
1049
1050 //******************************************************************************
1051
1052 IOPMrootDomain *
1053 IOPMrootDomain::construct( void )
1054 {
1055 IOPMrootDomain *root;
1056
1057 root = new IOPMrootDomain;
1058 if (root) {
1059 root->init();
1060 }
1061
1062 return root;
1063 }
1064
1065 //******************************************************************************
1066 // updateConsoleUsersCallout
1067 //
1068 //******************************************************************************
1069
1070 static void
1071 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1072 {
1073 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1074 rootDomain->updateConsoleUsers();
1075 }
1076
1077 void
1078 IOPMrootDomain::updateConsoleUsers(void)
1079 {
1080 IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1081 if (tasksSuspended) {
1082 tasksSuspended = FALSE;
1083 updateTasksSuspend();
1084 }
1085 }
1086
1087 void
1088 IOPMrootDomain::updateTasksSuspend(void)
1089 {
1090 bool newSuspend;
1091
1092 newSuspend = (tasksSuspended || _aotTasksSuspended);
1093 if (newSuspend == tasksSuspendState) {
1094 return;
1095 }
1096 tasksSuspendState = newSuspend;
1097 tasks_system_suspend(newSuspend);
1098 }
1099
1100 //******************************************************************************
1101
1102 static void
1103 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1104 {
1105 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1106 uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
1107 uint32_t powerState = rootDomain->getPowerState();
1108
1109 DLOG("disk_sync_callout ps=%u\n", powerState);
1110
1111 if (ON_STATE == powerState) {
1112 sync_internal();
1113
1114 #if HIBERNATION
1115 // Block sleep until trim issued on previous wake path is completed.
1116 IOHibernateSystemPostWake(true);
1117 #endif
1118 }
1119 #if HIBERNATION
1120 else {
1121 IOHibernateSystemPostWake(false);
1122
1123 rootDomain->sleepWakeDebugSaveSpinDumpFile();
1124 }
1125 #endif
1126
1127 rootDomain->allowPowerChange(notifyRef);
1128 DLOG("disk_sync_callout finish\n");
1129 }
1130
1131 //******************************************************************************
1132 static UInt32
1133 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1134 {
1135 AbsoluteTime endTime;
1136 UInt64 nano = 0;
1137
1138 clock_get_uptime(&endTime);
1139 if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1140 *elapsedTime = 0;
1141 } else {
1142 SUB_ABSOLUTETIME(&endTime, startTime);
1143 absolutetime_to_nanoseconds(endTime, &nano);
1144 *elapsedTime = endTime;
1145 }
1146
1147 return (UInt32)(nano / NSEC_PER_MSEC);
1148 }
1149
1150 //******************************************************************************
1151
1152 static int
1153 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1154 {
1155 struct timeval *swt = (struct timeval *)arg1;
1156 struct proc *p = req->p;
1157
1158 if (p == kernproc) {
1159 return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
1160 } else if (proc_is64bit(p)) {
1161 struct user64_timeval t = {};
1162 t.tv_sec = swt->tv_sec;
1163 t.tv_usec = swt->tv_usec;
1164 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1165 } else {
1166 struct user32_timeval t = {};
1167 t.tv_sec = (typeof(t.tv_sec))swt->tv_sec;
1168 t.tv_usec = swt->tv_usec;
1169 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1170 }
1171 }
1172
1173 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1174 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1175 &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1176
1177 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1178 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1179 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1180
1181 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
1182 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
1183 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
1184 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
1185
1186 static int
1187 sysctl_willshutdown
1188 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1189 {
1190 int new_value, changed;
1191 int error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1192 if (changed) {
1193 if (!gWillShutdown && (new_value == 1)) {
1194 IOPMRootDomainWillShutdown();
1195 } else {
1196 error = EINVAL;
1197 }
1198 }
1199 return error;
1200 }
1201
1202 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1203 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1204 NULL, 0, sysctl_willshutdown, "I", "");
1205
1206 extern struct sysctl_oid sysctl__kern_iokittest;
1207 extern struct sysctl_oid sysctl__debug_iokit;
1208
1209 #if defined(XNU_TARGET_OS_OSX)
1210
1211 static int
1212 sysctl_progressmeterenable
1213 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1214 {
1215 int error;
1216 int new_value, changed;
1217
1218 error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1219
1220 if (changed) {
1221 vc_enable_progressmeter(new_value);
1222 }
1223
1224 return error;
1225 }
1226
1227 static int
1228 sysctl_progressmeter
1229 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1230 {
1231 int error;
1232 int new_value, changed;
1233
1234 error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1235
1236 if (changed) {
1237 vc_set_progressmeter(new_value);
1238 }
1239
1240 return error;
1241 }
1242
1243 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1244 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1245 NULL, 0, sysctl_progressmeterenable, "I", "");
1246
1247 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1248 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1249 NULL, 0, sysctl_progressmeter, "I", "");
1250
1251 #endif /* defined(XNU_TARGET_OS_OSX) */
1252
1253
1254
1255 static int
1256 sysctl_consoleoptions
1257 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1258 {
1259 int error, changed;
1260 uint32_t new_value;
1261
1262 error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1263
1264 if (changed) {
1265 vc_user_options.options = new_value;
1266 }
1267
1268 return error;
1269 }
1270
1271 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1272 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1273 NULL, 0, sysctl_consoleoptions, "I", "");
1274
1275
1276 static int
1277 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1278 {
1279 return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1280 }
1281
1282 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1283 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1284 NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1285
1286
1287 static int
1288 sysctl_wakereason SYSCTL_HANDLER_ARGS
1289 {
1290 char wr[sizeof(gWakeReasonString)];
1291
1292 wr[0] = '\0';
1293 if (gRootDomain) {
1294 gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1295 }
1296
1297 return sysctl_io_string(req, wr, 0, 0, NULL);
1298 }
1299
1300 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1301 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1302 NULL, 0, sysctl_wakereason, "A", "wakereason");
1303
1304 SYSCTL_STRING(_kern, OID_AUTO, bootreason,
1305 CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1306 gBootReasonString, sizeof(gBootReasonString), "");
1307
1308 static int
1309 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1310 {
1311 char sr[sizeof(gShutdownReasonString)];
1312
1313 sr[0] = '\0';
1314 if (gRootDomain) {
1315 gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1316 }
1317
1318 return sysctl_io_string(req, sr, 0, 0, NULL);
1319 }
1320
1321 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1322 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1323 NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1324
1325 static int
1326 sysctl_targettype SYSCTL_HANDLER_ARGS
1327 {
1328 IOService * root;
1329 OSSharedPtr<OSObject> obj;
1330 OSData * data;
1331 char tt[32];
1332
1333 tt[0] = '\0';
1334 root = IOService::getServiceRoot();
1335 if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1336 if ((data = OSDynamicCast(OSData, obj.get()))) {
1337 strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1338 }
1339 }
1340 return sysctl_io_string(req, tt, 0, 0, NULL);
1341 }
1342
1343 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1344 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1345 NULL, 0, sysctl_targettype, "A", "targettype");
1346
1347 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1348 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1349 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1350 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1351 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1352 #if DEVELOPMENT || DEBUG
1353 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
1354 #if defined(XNU_TARGET_OS_OSX)
1355 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, "");
1356 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1357 #endif /* defined(XNU_TARGET_OS_OSX) */
1358 #endif /* DEVELOPMENT || DEBUG */
1359
1360 //******************************************************************************
1361 // AOT
1362
1363 static int
1364 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1365 {
1366 if (NULL == gRootDomain) {
1367 return ENOENT;
1368 }
1369 if (NULL == gRootDomain->_aotMetrics) {
1370 return ENOENT;
1371 }
1372 return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1373 }
1374
1375 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
1376 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1377 NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
1378
1379
1380 static int
1381 update_aotmode(uint32_t mode)
1382 {
1383 int result;
1384
1385 if (!gIOPMWorkLoop) {
1386 return ENOENT;
1387 }
1388 result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1389 unsigned int oldCount;
1390
1391 if (mode && !gRootDomain->_aotMetrics) {
1392 gRootDomain->_aotMetrics = IONewZero(IOPMAOTMetrics, 1);
1393 if (!gRootDomain->_aotMetrics) {
1394 return ENOMEM;
1395 }
1396 }
1397
1398 oldCount = gRootDomain->idleSleepPreventersCount();
1399 gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1400 gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1401 return 0;
1402 });
1403 return result;
1404 }
1405
1406 static int
1407 sysctl_aotmodebits
1408 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1409 {
1410 int error, changed;
1411 uint32_t new_value;
1412
1413 if (NULL == gRootDomain) {
1414 return ENOENT;
1415 }
1416 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1417 if (changed && gIOPMWorkLoop) {
1418 error = update_aotmode(new_value);
1419 }
1420
1421 return error;
1422 }
1423
1424 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1425 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1426 NULL, 0, sysctl_aotmodebits, "I", "");
1427
1428 static int
1429 sysctl_aotmode
1430 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1431 {
1432 int error, changed;
1433 uint32_t new_value;
1434
1435 if (NULL == gRootDomain) {
1436 return ENOENT;
1437 }
1438 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1439 if (changed && gIOPMWorkLoop) {
1440 if (new_value) {
1441 new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1442 }
1443 error = update_aotmode(new_value);
1444 }
1445
1446 return error;
1447 }
1448
1449 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
1450 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1451 NULL, 0, sysctl_aotmode, "I", "");
1452
1453 //******************************************************************************
1454
1455 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey;
1456 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey;
1457 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey;
1458 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey;
1459 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey;
1460 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey;
1461 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey;
1462 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey;
1463 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey;
1464 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey;
1465 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey;
1466 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey;
1467
1468 //******************************************************************************
1469 // start
1470 //
1471 //******************************************************************************
1472
1473 #define kRootDomainSettingsCount 20
1474 #define kRootDomainNoPublishSettingsCount 4
1475
1476 bool
1477 IOPMrootDomain::start( IOService * nub )
1478 {
1479 OSSharedPtr<OSIterator> psIterator;
1480 OSSharedPtr<OSDictionary> tmpDict;
1481
1482 super::start(nub);
1483
1484 gRootDomain = this;
1485 gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1486 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1487 gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
1488 gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
1489 gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1490 gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
1491 gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1492 gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1493 gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1494 gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1495 gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1496 gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey);
1497
1498 gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1499 gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1500 gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1501 gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1502 gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1503
1504 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1505 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1506 gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1507
1508 OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1509 {
1510 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1511 gIOPMSettingAutoWakeSecondsKey,
1512 gIOPMSettingAutoPowerSecondsKey,
1513 gIOPMSettingAutoWakeCalendarKey,
1514 gIOPMSettingAutoPowerCalendarKey,
1515 gIOPMSettingDebugWakeRelativeKey,
1516 gIOPMSettingDebugPowerRelativeKey,
1517 OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1518 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1519 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1520 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1521 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1522 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1523 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1524 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1525 OSSymbol::withCString(kIOPMStateConsoleShutdown),
1526 OSSymbol::withCString(kIOPMSettingProModeControl),
1527 OSSymbol::withCString(kIOPMSettingProModeDefer),
1528 gIOPMSettingSilentRunningKey,
1529 gIOPMSettingLowLatencyAudioModeKey,
1530 };
1531
1532 OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1533 {
1534 OSSymbol::withCString(kIOPMSettingProModeControl),
1535 OSSymbol::withCString(kIOPMSettingProModeDefer),
1536 gIOPMSettingSilentRunningKey,
1537 gIOPMSettingLowLatencyAudioModeKey,
1538 };
1539
1540 #if DEVELOPMENT || DEBUG
1541 #if defined(XNU_TARGET_OS_OSX)
1542 PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1543 PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags));
1544 #endif /* defined(XNU_TARGET_OS_OSX) */
1545 #endif /* DEVELOPMENT || DEBUG */
1546
1547 PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1548 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1549 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1550 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1551 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1552 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1553
1554 queue_init(&aggressivesQueue);
1555 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1556 aggressivesData = OSData::withCapacity(
1557 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1558
1559 featuresDictLock = IOLockAlloc();
1560 settingsCtrlLock = IOLockAlloc();
1561 wakeEventLock = IOLockAlloc();
1562 gHaltLogLock = IOLockAlloc();
1563 setPMRootDomain(this);
1564
1565 extraSleepTimer = thread_call_allocate(
1566 idleSleepTimerExpired,
1567 (thread_call_param_t) this);
1568
1569 powerButtonDown = thread_call_allocate(
1570 powerButtonDownCallout,
1571 (thread_call_param_t) this);
1572
1573 powerButtonUp = thread_call_allocate(
1574 powerButtonUpCallout,
1575 (thread_call_param_t) this);
1576
1577 diskSyncCalloutEntry = thread_call_allocate(
1578 &disk_sync_callout,
1579 (thread_call_param_t) this);
1580 updateConsoleUsersEntry = thread_call_allocate(
1581 &updateConsoleUsersCallout,
1582 (thread_call_param_t) this);
1583
1584 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1585 fullWakeThreadCall = thread_call_allocate_with_options(
1586 OSMemberFunctionCast(thread_call_func_t, this,
1587 &IOPMrootDomain::fullWakeDelayedWork),
1588 (thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL,
1589 THREAD_CALL_OPTIONS_ONCE);
1590 #endif
1591
1592 setProperty(kIOSleepSupportedKey, true);
1593
1594 bzero(&gPMStats, sizeof(gPMStats));
1595
1596 pmTracer = PMTraceWorker::tracer(this);
1597
1598 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1599
1600 userDisabledAllSleep = false;
1601 systemBooting = true;
1602 idleSleepEnabled = false;
1603 sleepSlider = 0;
1604 idleSleepTimerPending = false;
1605 wrangler = NULL;
1606 clamshellClosed = false;
1607 clamshellExists = false;
1608 #if DISPLAY_WRANGLER_PRESENT
1609 clamshellDisabled = true;
1610 #else
1611 clamshellDisabled = false;
1612 #endif
1613 clamshellIgnoreClose = false;
1614 acAdaptorConnected = true;
1615 clamshellSleepDisableMask = 0;
1616 gWakeReasonString[0] = '\0';
1617
1618 // Initialize to user active.
1619 // Will never transition to user inactive w/o wrangler.
1620 fullWakeReason = kFullWakeReasonLocalUser;
1621 userIsActive = userWasActive = true;
1622 clock_get_uptime(&gUserActiveAbsTime);
1623 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
1624
1625 // Set the default system capabilities at boot.
1626 _currentCapability = kIOPMSystemCapabilityCPU |
1627 kIOPMSystemCapabilityGraphics |
1628 kIOPMSystemCapabilityAudio |
1629 kIOPMSystemCapabilityNetwork;
1630
1631 _pendingCapability = _currentCapability;
1632 _desiredCapability = _currentCapability;
1633 _highestCapability = _currentCapability;
1634 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1635
1636 queuedSleepWakeUUIDString = NULL;
1637 initializeBootSessionUUID();
1638 pmStatsAppResponses = OSArray::withCapacity(5);
1639 _statsNameKey = OSSymbol::withCString(kIOPMStatsNameKey);
1640 _statsPIDKey = OSSymbol::withCString(kIOPMStatsPIDKey);
1641 _statsTimeMSKey = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1642 _statsResponseTypeKey = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1643 _statsMessageTypeKey = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1644 _statsPowerCapsKey = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1645 assertOnWakeSecs = -1;// Invalid value to prevent updates
1646
1647 pmStatsLock = IOLockAlloc();
1648 idxPMCPUClamshell = kCPUUnknownIndex;
1649 idxPMCPULimitedPower = kCPUUnknownIndex;
1650
1651 tmpDict = OSDictionary::withCapacity(1);
1652 setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1653
1654 // Set a default "SystemPowerProfileOverrideDict" for platform
1655 // drivers without any overrides.
1656 if (!propertyExists(kIOPMSystemDefaultOverrideKey)) {
1657 tmpDict = OSDictionary::withCapacity(1);
1658 setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get());
1659 }
1660
1661 settingsCallbacks = OSDictionary::withCapacity(1);
1662
1663 // Create a list of the valid PM settings that we'll relay to
1664 // interested clients in setProperties() => setPMSetting()
1665 allowedPMSettings = OSArray::withObjects(
1666 (const OSObject **)settingsArr,
1667 kRootDomainSettingsCount,
1668 0);
1669
1670 // List of PM settings that should not automatically publish itself
1671 // as a feature when registered by a listener.
1672 noPublishPMSettings = OSArray::withObjects(
1673 (const OSObject **)noPublishSettingsArr,
1674 kRootDomainNoPublishSettingsCount,
1675 0);
1676
1677 fPMSettingsDict = OSDictionary::withCapacity(5);
1678 preventIdleSleepList = OSSet::withCapacity(8);
1679 preventSystemSleepList = OSSet::withCapacity(2);
1680
1681 PMinit(); // creates gIOPMWorkLoop
1682 gIOPMWorkLoop = getIOPMWorkloop();
1683
1684 // Create IOPMPowerStateQueue used to queue external power
1685 // events, and to handle those events on the PM work loop.
1686 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1687 this, OSMemberFunctionCast(IOEventSource::Action, this,
1688 &IOPMrootDomain::dispatchPowerEvent));
1689 gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1690
1691 _aotMode = 0;
1692 _aotTimerES = IOTimerEventSource::timerEventSource(this,
1693 OSMemberFunctionCast(IOTimerEventSource::Action,
1694 this, &IOPMrootDomain::aotEvaluate));
1695 gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1696
1697 // create our power parent
1698 gPatriarch = new IORootParent;
1699 gPatriarch->init();
1700 gPatriarch->attach(this);
1701 gPatriarch->start(this);
1702 gPatriarch->addPowerChild(this);
1703
1704 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1705 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1706
1707 // install power change handler
1708 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1709
1710 #if DISPLAY_WRANGLER_PRESENT
1711 wranglerIdleSettings = OSDictionary::withCapacity(1);
1712 OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1713
1714 if (wranglerIdleSettings && wranglerIdlePeriod) {
1715 wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1716 wranglerIdlePeriod.get());
1717 }
1718
1719 #endif /* DISPLAY_WRANGLER_PRESENT */
1720
1721 lowLatencyAudioNotifierDict = OSDictionary::withCapacity(2);
1722 lowLatencyAudioNotifyStateSym = OSSymbol::withCString("LowLatencyAudioNotifyState");
1723 lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1724 lowLatencyAudioNotifyStateVal = OSNumber::withNumber(0ull, 32);
1725 lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64);
1726
1727 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1728 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1729 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1730 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1731 }
1732
1733 OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1734 setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1735
1736 // IOBacklightDisplay can take a long time to load at boot, or it may
1737 // not load at all if you're booting with clamshell closed. We publish
1738 // 'DisplayDims' here redundantly to get it published early and at all.
1739 OSSharedPtr<OSDictionary> matching;
1740 matching = serviceMatching("IOPMPowerSource");
1741 psIterator = getMatchingServices(matching.get());
1742
1743 if (psIterator && psIterator->getNextObject()) {
1744 // There's at least one battery on the system, so we publish
1745 // 'DisplayDims' support for the LCD.
1746 publishFeature("DisplayDims");
1747 }
1748
1749 // read swd_panic boot-arg
1750 PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1751 sysctl_register_oid(&sysctl__kern_sleeptime);
1752 sysctl_register_oid(&sysctl__kern_waketime);
1753 sysctl_register_oid(&sysctl__kern_willshutdown);
1754 sysctl_register_oid(&sysctl__kern_iokittest);
1755 sysctl_register_oid(&sysctl__debug_iokit);
1756 sysctl_register_oid(&sysctl__hw_targettype);
1757
1758 #if defined(XNU_TARGET_OS_OSX)
1759 sysctl_register_oid(&sysctl__kern_progressmeterenable);
1760 sysctl_register_oid(&sysctl__kern_progressmeter);
1761 sysctl_register_oid(&sysctl__kern_wakereason);
1762 #endif /* defined(XNU_TARGET_OS_OSX) */
1763 sysctl_register_oid(&sysctl__kern_consoleoptions);
1764 sysctl_register_oid(&sysctl__kern_progressoptions);
1765
1766 sysctl_register_oid(&sysctl__kern_aotmode);
1767 sysctl_register_oid(&sysctl__kern_aotmodebits);
1768 sysctl_register_oid(&sysctl__kern_aotmetrics);
1769
1770 #if HIBERNATION
1771 #if defined(__arm64__)
1772 #endif /* defined(__arm64__) */
1773 IOHibernateSystemInit(this);
1774 #endif
1775
1776 registerService(); // let clients find us
1777
1778 return true;
1779 }
1780
1781 //******************************************************************************
1782 // setProperties
1783 //
1784 // Receive a setProperty call
1785 // The "System Boot" property means the system is completely booted.
1786 //******************************************************************************
1787
1788 IOReturn
1789 IOPMrootDomain::setProperties( OSObject * props_obj )
1790 {
1791 IOReturn return_value = kIOReturnSuccess;
1792 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
1793 OSBoolean *b = NULL;
1794 OSNumber *n = NULL;
1795 const OSSymbol *key = NULL;
1796 OSObject *obj = NULL;
1797 OSSharedPtr<OSCollectionIterator> iter;
1798
1799 if (!dict) {
1800 return kIOReturnBadArgument;
1801 }
1802
1803 bool clientEntitled = false;
1804 {
1805 OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1806 clientEntitled = (obj == kOSBooleanTrue);
1807 }
1808
1809 if (!clientEntitled) {
1810 const char * errorSuffix = NULL;
1811
1812 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1813 // That API can set 6 possible keys that are checked below.
1814 if ((dict->getCount() == 1) &&
1815 (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) ||
1816 dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) ||
1817 dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) ||
1818 dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) ||
1819 dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) ||
1820 dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) {
1821 return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
1822 if (return_value != kIOReturnSuccess) {
1823 errorSuffix = "privileged";
1824 }
1825 } else {
1826 return_value = kIOReturnNotPermitted;
1827 errorSuffix = "entitled";
1828 }
1829
1830 if (return_value != kIOReturnSuccess) {
1831 OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain);
1832 DLOG("%s failed, process %s is not %s\n", __func__,
1833 procName ? procName->getCStringNoCopy() : "", errorSuffix);
1834 return return_value;
1835 }
1836 }
1837
1838 OSSharedPtr<const OSSymbol> publish_simulated_battery_string = OSSymbol::withCString("SoftwareSimulatedBatteries");
1839 OSSharedPtr<const OSSymbol> boot_complete_string = OSSymbol::withCString("System Boot Complete");
1840 OSSharedPtr<const OSSymbol> sys_shutdown_string = OSSymbol::withCString("System Shutdown");
1841 OSSharedPtr<const OSSymbol> stall_halt_string = OSSymbol::withCString("StallSystemAtHalt");
1842 OSSharedPtr<const OSSymbol> battery_warning_disabled_string = OSSymbol::withCString("BatteryWarningsDisabled");
1843 OSSharedPtr<const OSSymbol> idle_seconds_string = OSSymbol::withCString("System Idle Seconds");
1844 OSSharedPtr<const OSSymbol> sleepdisabled_string = OSSymbol::withCString("SleepDisabled");
1845 OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1846 OSSharedPtr<const OSSymbol> loginwindow_progress_string = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1847 OSSharedPtr<const OSSymbol> coredisplay_progress_string = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1848 OSSharedPtr<const OSSymbol> coregraphics_progress_string = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1849 #if DEBUG || DEVELOPMENT
1850 OSSharedPtr<const OSSymbol> clamshell_close_string = OSSymbol::withCString("IOPMTestClamshellClose");
1851 OSSharedPtr<const OSSymbol> clamshell_open_string = OSSymbol::withCString("IOPMTestClamshellOpen");
1852 OSSharedPtr<const OSSymbol> ac_detach_string = OSSymbol::withCString("IOPMTestACDetach");
1853 OSSharedPtr<const OSSymbol> ac_attach_string = OSSymbol::withCString("IOPMTestACAttach");
1854 OSSharedPtr<const OSSymbol> desktopmode_set_string = OSSymbol::withCString("IOPMTestDesktopModeSet");
1855 OSSharedPtr<const OSSymbol> desktopmode_remove_string = OSSymbol::withCString("IOPMTestDesktopModeRemove");
1856 #endif
1857
1858 #if HIBERNATION
1859 OSSharedPtr<const OSSymbol> hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey);
1860 OSSharedPtr<const OSSymbol> hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey);
1861 OSSharedPtr<const OSSymbol> hibernatefilemin_string = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
1862 OSSharedPtr<const OSSymbol> hibernatefilemax_string = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
1863 OSSharedPtr<const OSSymbol> hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey);
1864 OSSharedPtr<const OSSymbol> hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey);
1865 #endif
1866
1867 iter = OSCollectionIterator::withCollection(dict);
1868 if (!iter) {
1869 return_value = kIOReturnNoMemory;
1870 goto exit;
1871 }
1872
1873 while ((key = (const OSSymbol *) iter->getNextObject()) &&
1874 (obj = dict->getObject(key))) {
1875 if (key->isEqualTo(publish_simulated_battery_string.get())) {
1876 if (OSDynamicCast(OSBoolean, obj)) {
1877 publishResource(key, kOSBooleanTrue);
1878 }
1879 } else if (key->isEqualTo(idle_seconds_string.get())) {
1880 if ((n = OSDynamicCast(OSNumber, obj))) {
1881 setProperty(key, n);
1882 idleSeconds = n->unsigned32BitValue();
1883 }
1884 } else if (key->isEqualTo(boot_complete_string.get())) {
1885 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
1886 } else if (key->isEqualTo(sys_shutdown_string.get())) {
1887 if ((b = OSDynamicCast(OSBoolean, obj))) {
1888 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
1889 }
1890 } else if (key->isEqualTo(battery_warning_disabled_string.get())) {
1891 setProperty(key, obj);
1892 }
1893 #if HIBERNATION
1894 else if (key->isEqualTo(hibernatemode_string.get()) ||
1895 key->isEqualTo(hibernatefilemin_string.get()) ||
1896 key->isEqualTo(hibernatefilemax_string.get()) ||
1897 key->isEqualTo(hibernatefreeratio_string.get()) ||
1898 key->isEqualTo(hibernatefreetime_string.get())) {
1899 if ((n = OSDynamicCast(OSNumber, obj))) {
1900 setProperty(key, n);
1901 }
1902 } else if (key->isEqualTo(hibernatefile_string.get())) {
1903 OSString * str = OSDynamicCast(OSString, obj);
1904 if (str) {
1905 setProperty(key, str);
1906 }
1907 }
1908 #endif
1909 else if (key->isEqualTo(sleepdisabled_string.get())) {
1910 if ((b = OSDynamicCast(OSBoolean, obj))) {
1911 setProperty(key, b);
1912 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1913 }
1914 } else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
1915 obj->retain();
1916 pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
1917 } else if (key->isEqualTo(loginwindow_progress_string.get())) {
1918 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1919 uint32_t data = n->unsigned32BitValue();
1920 pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
1921 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
1922 }
1923 } else if (key->isEqualTo(coredisplay_progress_string.get())) {
1924 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1925 uint32_t data = n->unsigned32BitValue();
1926 pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
1927 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
1928 }
1929 } else if (key->isEqualTo(coregraphics_progress_string.get())) {
1930 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1931 uint32_t data = n->unsigned32BitValue();
1932 pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
1933 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
1934 }
1935 } else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
1936 key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
1937 key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
1938 key->isEqualTo(stall_halt_string.get())) {
1939 if ((b = OSDynamicCast(OSBoolean, obj))) {
1940 setProperty(key, b);
1941 }
1942 } else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
1943 key->isEqualTo(kIOPMDeepSleepTimerKey) ||
1944 key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
1945 key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
1946 if ((n = OSDynamicCast(OSNumber, obj))) {
1947 setProperty(key, n);
1948 }
1949 } else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
1950 if (kOSBooleanTrue == obj) {
1951 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
1952 } else {
1953 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
1954 }
1955 DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
1956 }
1957 #if DEBUG || DEVELOPMENT
1958 else if (key->isEqualTo(clamshell_close_string.get())) {
1959 DLOG("SetProperties: setting clamshell close\n");
1960 UInt32 msg = kIOPMClamshellClosed;
1961 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
1962 } else if (key->isEqualTo(clamshell_open_string.get())) {
1963 DLOG("SetProperties: setting clamshell open\n");
1964 UInt32 msg = kIOPMClamshellOpened;
1965 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
1966 } else if (key->isEqualTo(ac_detach_string.get())) {
1967 DLOG("SetProperties: setting ac detach\n");
1968 UInt32 msg = kIOPMSetACAdaptorConnected;
1969 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
1970 } else if (key->isEqualTo(ac_attach_string.get())) {
1971 DLOG("SetProperties: setting ac attach\n");
1972 UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue;
1973 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
1974 } else if (key->isEqualTo(desktopmode_set_string.get())) {
1975 DLOG("SetProperties: setting desktopmode");
1976 UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue;
1977 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
1978 } else if (key->isEqualTo(desktopmode_remove_string.get())) {
1979 DLOG("SetProperties: removing desktopmode\n");
1980 UInt32 msg = kIOPMSetDesktopMode;
1981 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
1982 }
1983 #endif
1984 // Relay our allowed PM settings onto our registered PM clients
1985 else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
1986 return_value = setPMSetting(key, obj);
1987 if (kIOReturnSuccess != return_value) {
1988 break;
1989 }
1990 } else {
1991 DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
1992 }
1993 }
1994
1995 exit:
1996 return return_value;
1997 }
1998
1999 // MARK: -
2000 // MARK: Aggressiveness
2001
2002 //******************************************************************************
2003 // setAggressiveness
2004 //
2005 // Override IOService::setAggressiveness()
2006 //******************************************************************************
2007
2008 IOReturn
2009 IOPMrootDomain::setAggressiveness(
2010 unsigned long type,
2011 unsigned long value )
2012 {
2013 return setAggressiveness( type, value, 0 );
2014 }
2015
2016 /*
2017 * Private setAggressiveness() with an internal options argument.
2018 */
2019 IOReturn
2020 IOPMrootDomain::setAggressiveness(
2021 unsigned long type,
2022 unsigned long value,
2023 IOOptionBits options )
2024 {
2025 AggressivesRequest * entry;
2026 AggressivesRequest * request;
2027 bool found = false;
2028
2029 if ((type > UINT_MAX) || (value > UINT_MAX)) {
2030 return kIOReturnBadArgument;
2031 }
2032
2033 if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2034 DLOG("setAggressiveness(%x) %s = %u\n",
2035 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2036 } else {
2037 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2038 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2039 }
2040
2041 request = IONew(AggressivesRequest, 1);
2042 if (!request) {
2043 return kIOReturnNoMemory;
2044 }
2045
2046 memset(request, 0, sizeof(*request));
2047 request->options = options;
2048 request->dataType = kAggressivesRequestTypeRecord;
2049 request->data.record.type = (uint32_t) type;
2050 request->data.record.value = (uint32_t) value;
2051
2052 AGGRESSIVES_LOCK();
2053
2054 // Update disk quick spindown flag used by getAggressiveness().
2055 // Never merge requests with quick spindown flags set.
2056
2057 if (options & kAggressivesOptionQuickSpindownEnable) {
2058 gAggressivesState |= kAggressivesStateQuickSpindown;
2059 } else if (options & kAggressivesOptionQuickSpindownDisable) {
2060 gAggressivesState &= ~kAggressivesStateQuickSpindown;
2061 } else {
2062 // Coalesce requests with identical aggressives types.
2063 // Deal with callers that calls us too "aggressively".
2064
2065 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2066 {
2067 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2068 (entry->data.record.type == type) &&
2069 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2070 entry->data.record.value = (uint32_t) value;
2071 found = true;
2072 break;
2073 }
2074 }
2075 }
2076
2077 if (!found) {
2078 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2079 }
2080
2081 AGGRESSIVES_UNLOCK();
2082
2083 if (found) {
2084 IODelete(request, AggressivesRequest, 1);
2085 }
2086
2087 if (options & kAggressivesOptionSynchronous) {
2088 handleAggressivesRequests(); // not truly synchronous
2089 } else {
2090 thread_call_enter(aggressivesThreadCall);
2091 }
2092
2093 return kIOReturnSuccess;
2094 }
2095
2096 //******************************************************************************
2097 // getAggressiveness
2098 //
2099 // Override IOService::setAggressiveness()
2100 // Fetch the aggressiveness factor with the given type.
2101 //******************************************************************************
2102
2103 IOReturn
2104 IOPMrootDomain::getAggressiveness(
2105 unsigned long type,
2106 unsigned long * outLevel )
2107 {
2108 uint32_t value = 0;
2109 int source = 0;
2110
2111 if (!outLevel || (type > UINT_MAX)) {
2112 return kIOReturnBadArgument;
2113 }
2114
2115 AGGRESSIVES_LOCK();
2116
2117 // Disk quick spindown in effect, report value = 1
2118
2119 if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2120 (type == kPMMinutesToSpinDown)) {
2121 value = kAggressivesMinValue;
2122 source = 1;
2123 }
2124
2125 // Consult the pending request queue.
2126
2127 if (!source) {
2128 AggressivesRequest * entry;
2129
2130 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2131 {
2132 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2133 (entry->data.record.type == type) &&
2134 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2135 value = entry->data.record.value;
2136 source = 2;
2137 break;
2138 }
2139 }
2140 }
2141
2142 // Consult the backend records.
2143
2144 if (!source && aggressivesData) {
2145 AggressivesRecord * record;
2146 int i, count;
2147
2148 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2149 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2150
2151 for (i = 0; i < count; i++, record++) {
2152 if (record->type == type) {
2153 value = record->value;
2154 source = 3;
2155 break;
2156 }
2157 }
2158 }
2159
2160 AGGRESSIVES_UNLOCK();
2161
2162 if (source) {
2163 *outLevel = (unsigned long) value;
2164 return kIOReturnSuccess;
2165 } else {
2166 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
2167 *outLevel = 0; // default return = 0, driver may not check for error
2168 return kIOReturnInvalid;
2169 }
2170 }
2171
2172 //******************************************************************************
2173 // joinAggressiveness
2174 //
2175 // Request from IOService to join future aggressiveness broadcasts.
2176 //******************************************************************************
2177
2178 IOReturn
2179 IOPMrootDomain::joinAggressiveness(
2180 IOService * service )
2181 {
2182 AggressivesRequest * request;
2183
2184 if (!service || (service == this)) {
2185 return kIOReturnBadArgument;
2186 }
2187
2188 DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2189
2190 request = IONew(AggressivesRequest, 1);
2191 if (!request) {
2192 return kIOReturnNoMemory;
2193 }
2194
2195 memset(request, 0, sizeof(*request));
2196 request->dataType = kAggressivesRequestTypeService;
2197 request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2198
2199 AGGRESSIVES_LOCK();
2200 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2201 AGGRESSIVES_UNLOCK();
2202
2203 thread_call_enter(aggressivesThreadCall);
2204
2205 return kIOReturnSuccess;
2206 }
2207
2208 //******************************************************************************
2209 // handleAggressivesRequests
2210 //
2211 // Backend thread processes all incoming aggressiveness requests in the queue.
2212 //******************************************************************************
2213
2214 static void
2215 handleAggressivesFunction(
2216 thread_call_param_t param1,
2217 thread_call_param_t param2 )
2218 {
2219 if (param1) {
2220 ((IOPMrootDomain *) param1)->handleAggressivesRequests();
2221 }
2222 }
2223
2224 void
2225 IOPMrootDomain::handleAggressivesRequests( void )
2226 {
2227 AggressivesRecord * start;
2228 AggressivesRecord * record;
2229 AggressivesRequest * request;
2230 queue_head_t joinedQueue;
2231 int i, count;
2232 bool broadcast;
2233 bool found;
2234 bool pingSelf = false;
2235
2236 AGGRESSIVES_LOCK();
2237
2238 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2239 queue_empty(&aggressivesQueue)) {
2240 goto unlock_done;
2241 }
2242
2243 gAggressivesState |= kAggressivesStateBusy;
2244 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2245 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2246
2247 do{
2248 broadcast = false;
2249 queue_init(&joinedQueue);
2250
2251 do{
2252 // Remove request from the incoming queue in FIFO order.
2253 queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
2254 switch (request->dataType) {
2255 case kAggressivesRequestTypeRecord:
2256 // Update existing record if found.
2257 found = false;
2258 for (i = 0, record = start; i < count; i++, record++) {
2259 if (record->type == request->data.record.type) {
2260 found = true;
2261
2262 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2263 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2264 broadcast = true;
2265 record->flags |= (kAggressivesRecordFlagMinValue |
2266 kAggressivesRecordFlagModified);
2267 DLOG("disk spindown accelerated, was %u min\n",
2268 record->value);
2269 }
2270 } else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2271 if (record->flags & kAggressivesRecordFlagMinValue) {
2272 broadcast = true;
2273 record->flags |= kAggressivesRecordFlagModified;
2274 record->flags &= ~kAggressivesRecordFlagMinValue;
2275 DLOG("disk spindown restored to %u min\n",
2276 record->value);
2277 }
2278 } else if (record->value != request->data.record.value) {
2279 record->value = request->data.record.value;
2280 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2281 broadcast = true;
2282 record->flags |= kAggressivesRecordFlagModified;
2283 }
2284 }
2285 break;
2286 }
2287 }
2288
2289 // No matching record, append a new record.
2290 if (!found &&
2291 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2292 AggressivesRecord newRecord;
2293
2294 newRecord.flags = kAggressivesRecordFlagModified;
2295 newRecord.type = request->data.record.type;
2296 newRecord.value = request->data.record.value;
2297 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2298 newRecord.flags |= kAggressivesRecordFlagMinValue;
2299 DLOG("disk spindown accelerated\n");
2300 }
2301
2302 aggressivesData->appendBytes(&newRecord, sizeof(newRecord));
2303
2304 // OSData may have switched to another (larger) buffer.
2305 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2306 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2307 broadcast = true;
2308 }
2309
2310 // Finished processing the request, release it.
2311 IODelete(request, AggressivesRequest, 1);
2312 break;
2313
2314 case kAggressivesRequestTypeService:
2315 // synchronizeAggressives() will free request.
2316 queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2317 break;
2318
2319 default:
2320 panic("bad aggressives request type %x\n", request->dataType);
2321 break;
2322 }
2323 } while (!queue_empty(&aggressivesQueue));
2324
2325 // Release the lock to perform work, with busy flag set.
2326 if (!queue_empty(&joinedQueue) || broadcast) {
2327 AGGRESSIVES_UNLOCK();
2328 if (!queue_empty(&joinedQueue)) {
2329 synchronizeAggressives(&joinedQueue, start, count);
2330 }
2331 if (broadcast) {
2332 broadcastAggressives(start, count);
2333 }
2334 AGGRESSIVES_LOCK();
2335 }
2336
2337 // Remove the modified flag from all records.
2338 for (i = 0, record = start; i < count; i++, record++) {
2339 if ((record->flags & kAggressivesRecordFlagModified) &&
2340 ((record->type == kPMMinutesToDim) ||
2341 (record->type == kPMMinutesToSleep))) {
2342 pingSelf = true;
2343 }
2344
2345 record->flags &= ~kAggressivesRecordFlagModified;
2346 }
2347
2348 // Check the incoming queue again since new entries may have been
2349 // added while lock was released above.
2350 } while (!queue_empty(&aggressivesQueue));
2351
2352 gAggressivesState &= ~kAggressivesStateBusy;
2353
2354 unlock_done:
2355 AGGRESSIVES_UNLOCK();
2356
2357 // Root domain is interested in system and display sleep slider changes.
2358 // Submit a power event to handle those changes on the PM work loop.
2359
2360 if (pingSelf && pmPowerStateQueue) {
2361 pmPowerStateQueue->submitPowerEvent(
2362 kPowerEventPolicyStimulus,
2363 (void *) kStimulusAggressivenessChanged );
2364 }
2365 }
2366
2367 //******************************************************************************
2368 // synchronizeAggressives
2369 //
2370 // Push all known aggressiveness records to one or more IOService.
2371 //******************************************************************************
2372
2373 void
2374 IOPMrootDomain::synchronizeAggressives(
2375 queue_head_t * joinedQueue,
2376 const AggressivesRecord * array,
2377 int count )
2378 {
2379 OSSharedPtr<IOService> service;
2380 AggressivesRequest * request;
2381 const AggressivesRecord * record;
2382 IOPMDriverCallEntry callEntry;
2383 uint32_t value;
2384 int i;
2385
2386 while (!queue_empty(joinedQueue)) {
2387 queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
2388 if (request->dataType == kAggressivesRequestTypeService) {
2389 // retained by joinAggressiveness(), so take ownership
2390 service = os::move(request->data.service);
2391 } else {
2392 service.reset();
2393 }
2394
2395 IODelete(request, AggressivesRequest, 1);
2396 request = NULL;
2397
2398 if (service) {
2399 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2400 for (i = 0, record = array; i < count; i++, record++) {
2401 value = record->value;
2402 if (record->flags & kAggressivesRecordFlagMinValue) {
2403 value = kAggressivesMinValue;
2404 }
2405
2406 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2407 record->type, value, service->getName());
2408 service->setAggressiveness(record->type, value);
2409 }
2410 service->deassertPMDriverCall(&callEntry);
2411 }
2412 }
2413 }
2414 }
2415
2416 //******************************************************************************
2417 // broadcastAggressives
2418 //
2419 // Traverse PM tree and call setAggressiveness() for records that have changed.
2420 //******************************************************************************
2421
2422 void
2423 IOPMrootDomain::broadcastAggressives(
2424 const AggressivesRecord * array,
2425 int count )
2426 {
2427 OSSharedPtr<IORegistryIterator> iter;
2428 IORegistryEntry *entry;
2429 OSSharedPtr<IORegistryEntry> child;
2430 IOPowerConnection *connect;
2431 IOService *service;
2432 const AggressivesRecord *record;
2433 IOPMDriverCallEntry callEntry;
2434 uint32_t value;
2435 int i;
2436
2437 iter = IORegistryIterator::iterateOver(
2438 this, gIOPowerPlane, kIORegistryIterateRecursively);
2439 if (iter) {
2440 do{
2441 // !! reset the iterator
2442 iter->reset();
2443 while ((entry = iter->getNextObject())) {
2444 connect = OSDynamicCast(IOPowerConnection, entry);
2445 if (!connect || !connect->getReadyFlag()) {
2446 continue;
2447 }
2448
2449 child = connect->copyChildEntry(gIOPowerPlane);
2450 if (child) {
2451 if ((service = OSDynamicCast(IOService, child.get()))) {
2452 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2453 for (i = 0, record = array; i < count; i++, record++) {
2454 if (record->flags & kAggressivesRecordFlagModified) {
2455 value = record->value;
2456 if (record->flags & kAggressivesRecordFlagMinValue) {
2457 value = kAggressivesMinValue;
2458 }
2459 _LOG("broadcastAggressives %x = %u to %s\n",
2460 record->type, value, service->getName());
2461 service->setAggressiveness(record->type, value);
2462 }
2463 }
2464 service->deassertPMDriverCall(&callEntry);
2465 }
2466 }
2467 }
2468 }
2469 }while (!entry && !iter->isValid());
2470 }
2471 }
2472
2473 //*****************************************
2474 // stackshot on power button press
2475 // ***************************************
2476 static void
2477 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2478 {
2479 /* Power button pressed during wake
2480 * Take a stackshot
2481 */
2482 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2483 ((IOPMrootDomain *)us)->takeStackshot(false);
2484 }
2485
2486 static void
2487 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2488 {
2489 /* Power button released.
2490 * Delete any stackshot data
2491 */
2492 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2493 ((IOPMrootDomain *)us)->deleteStackshot();
2494 }
2495 //*************************************************************************
2496 //
2497
2498 // MARK: -
2499 // MARK: System Sleep
2500
2501 //******************************************************************************
2502 // startIdleSleepTimer
2503 //
2504 //******************************************************************************
2505
2506 void
2507 IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds )
2508 {
2509 AbsoluteTime deadline;
2510
2511 ASSERT_GATED();
2512 if (gNoIdleFlag) {
2513 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2514 return;
2515 }
2516 if (inSeconds) {
2517 clock_interval_to_deadline(inSeconds, kSecondScale, &deadline);
2518 thread_call_enter_delayed(extraSleepTimer, deadline);
2519 idleSleepTimerPending = true;
2520 } else {
2521 thread_call_enter(extraSleepTimer);
2522 }
2523 DLOG("idle timer set for %u seconds\n", inSeconds);
2524 }
2525
2526 //******************************************************************************
2527 // cancelIdleSleepTimer
2528 //
2529 //******************************************************************************
2530
2531 void
2532 IOPMrootDomain::cancelIdleSleepTimer( void )
2533 {
2534 ASSERT_GATED();
2535 if (idleSleepTimerPending) {
2536 DLOG("idle timer cancelled\n");
2537 thread_call_cancel(extraSleepTimer);
2538 idleSleepTimerPending = false;
2539
2540 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2541 AbsoluteTime now;
2542 clock_usec_t microsecs;
2543 clock_get_uptime(&now);
2544 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2545 absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
2546 if (assertOnWakeReport) {
2547 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2548 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2549 }
2550 }
2551 }
2552 }
2553
2554 //******************************************************************************
2555 // idleSleepTimerExpired
2556 //
2557 //******************************************************************************
2558
2559 static void
2560 idleSleepTimerExpired(
2561 thread_call_param_t us, thread_call_param_t )
2562 {
2563 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2564 }
2565
2566 //******************************************************************************
2567 // handleSleepTimerExpiration
2568 //
2569 // The time between the sleep idle timeout and the next longest one has elapsed.
2570 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2571 //******************************************************************************
2572
2573 void
2574 IOPMrootDomain::handleSleepTimerExpiration( void )
2575 {
2576 if (!gIOPMWorkLoop->inGate()) {
2577 gIOPMWorkLoop->runAction(
2578 OSMemberFunctionCast(IOWorkLoop::Action, this,
2579 &IOPMrootDomain::handleSleepTimerExpiration),
2580 this);
2581 return;
2582 }
2583
2584 DLOG("sleep timer expired\n");
2585 ASSERT_GATED();
2586
2587 idleSleepTimerPending = false;
2588 setQuickSpinDownTimeout();
2589 adjustPowerState(true);
2590 }
2591
2592 //******************************************************************************
2593 // getTimeToIdleSleep
2594 //
2595 // Returns number of seconds left before going into idle sleep.
2596 // Caller has to make sure that idle sleep is allowed at the time of calling
2597 // this function
2598 //******************************************************************************
2599
2600 uint32_t
2601 IOPMrootDomain::getTimeToIdleSleep( void )
2602 {
2603 AbsoluteTime now, lastActivityTime;
2604 uint64_t nanos;
2605 uint32_t minutesSinceUserInactive = 0;
2606 uint32_t sleepDelay = 0;
2607
2608 if (!idleSleepEnabled) {
2609 return 0xffffffff;
2610 }
2611
2612 if (userActivityTime) {
2613 lastActivityTime = userActivityTime;
2614 } else {
2615 lastActivityTime = userBecameInactiveTime;
2616 }
2617
2618 // Ignore any lastActivityTime that predates the last system wake.
2619 // The goal is to avoid a sudden idle sleep right after a dark wake
2620 // due to sleepDelay=0 computed below. The alternative 60s minimum
2621 // timeout should be large enough to allow dark wake to complete,
2622 // at which point the idle timer will be promptly cancelled.
2623 clock_get_uptime(&now);
2624 if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) &&
2625 (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) {
2626 SUB_ABSOLUTETIME(&now, &lastActivityTime);
2627 absolutetime_to_nanoseconds(now, &nanos);
2628 minutesSinceUserInactive = nanos / (60000000000ULL);
2629
2630 if (minutesSinceUserInactive >= sleepSlider) {
2631 sleepDelay = 0;
2632 } else {
2633 sleepDelay = sleepSlider - minutesSinceUserInactive;
2634 }
2635 } else {
2636 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2637 lastActivityTime, now, gIOLastWakeAbsTime);
2638 sleepDelay = sleepSlider;
2639 }
2640
2641 DLOG("user inactive %u min, time to idle sleep %u min\n",
2642 minutesSinceUserInactive, sleepDelay);
2643
2644 return sleepDelay * 60;
2645 }
2646
2647 //******************************************************************************
2648 // setQuickSpinDownTimeout
2649 //
2650 //******************************************************************************
2651
2652 void
2653 IOPMrootDomain::setQuickSpinDownTimeout( void )
2654 {
2655 ASSERT_GATED();
2656 setAggressiveness(
2657 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2658 }
2659
2660 //******************************************************************************
2661 // restoreUserSpinDownTimeout
2662 //
2663 //******************************************************************************
2664
2665 void
2666 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2667 {
2668 ASSERT_GATED();
2669 setAggressiveness(
2670 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2671 }
2672
2673 //******************************************************************************
2674 // sleepSystem
2675 //
2676 //******************************************************************************
2677
2678 /* public */
2679 IOReturn
2680 IOPMrootDomain::sleepSystem( void )
2681 {
2682 return sleepSystemOptions(NULL);
2683 }
2684
2685 /* private */
2686 IOReturn
2687 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2688 {
2689 OSObject *obj = NULL;
2690 OSString *reason = NULL;
2691 /* sleepSystem is a public function, and may be called by any kernel driver.
2692 * And that's bad - drivers should sleep the system by calling
2693 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2694 *
2695 * Note that user space app calls to IOPMSleepSystem() will also travel
2696 * this code path and thus be correctly identified as software sleeps.
2697 */
2698
2699 if (options && options->getObject("OSSwitch")) {
2700 // Log specific sleep cause for OS Switch hibernation
2701 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2702 }
2703
2704 if (options && (obj = options->getObject("Sleep Reason"))) {
2705 reason = OSDynamicCast(OSString, obj);
2706 if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2707 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2708 }
2709 if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2710 return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2711 }
2712 }
2713
2714 return privateSleepSystem( kIOPMSleepReasonSoftware);
2715 }
2716
2717 /* private */
2718 IOReturn
2719 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2720 {
2721 /* Called from both gated and non-gated context */
2722
2723 if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2724 return kIOReturnNotPermitted;
2725 }
2726
2727 pmPowerStateQueue->submitPowerEvent(
2728 kPowerEventPolicyStimulus,
2729 (void *) kStimulusDemandSystemSleep,
2730 sleepReason);
2731
2732 return kIOReturnSuccess;
2733 }
2734
2735 //******************************************************************************
2736 // powerChangeDone
2737 //
2738 // This overrides powerChangeDone in IOService.
2739 //******************************************************************************
2740 void
2741 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2742 {
2743 #if !__i386__ && !__x86_64__
2744 uint64_t timeSinceReset = 0;
2745 #endif
2746 uint64_t now;
2747 unsigned long newState;
2748 clock_sec_t secs;
2749 clock_usec_t microsecs;
2750 uint32_t lastDebugWakeSeconds;
2751 clock_sec_t adjWakeTime;
2752 IOPMCalendarStruct nowCalendar;
2753
2754 ASSERT_GATED();
2755 newState = getPowerState();
2756 DLOG("PowerChangeDone: %s->%s\n",
2757 getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2758
2759 if (previousPowerState == newState) {
2760 return;
2761 }
2762
2763 notifierThread = current_thread();
2764 switch (getPowerState()) {
2765 case SLEEP_STATE: {
2766 if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2767 secs = 0;
2768 microsecs = 0;
2769 PEGetUTCTimeOfDay(&secs, &microsecs);
2770
2771 adjWakeTime = 0;
2772 if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) {
2773 IOLog("use _calendarWakeAlarmUTC\n");
2774 adjWakeTime = _calendarWakeAlarmUTC;
2775 } else if (_aotExit || (kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) {
2776 IOLog("accelerate _aotWakeTime for exit\n");
2777 adjWakeTime = secs;
2778 } else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2779 IOLog("accelerate _aotWakeTime for assertion\n");
2780 adjWakeTime = secs;
2781 }
2782 if (adjWakeTime) {
2783 IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2784 }
2785
2786 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2787 IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2788
2789 IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2790 assert(kIOReturnSuccess == ret);
2791 }
2792 if (_aotLastWakeTime) {
2793 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
2794 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
2795 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
2796 gWakeReasonString,
2797 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2798 }
2799 }
2800 _aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2801 if (_aotTimerScheduled) {
2802 _aotTimerES->cancelTimeout();
2803 _aotTimerScheduled = false;
2804 }
2805 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2806
2807 // re-enable this timer for next sleep
2808 cancelIdleSleepTimer();
2809
2810 if (clamshellExists) {
2811 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
2812 if (gClamshellFlags & kClamshell_WAR_58009435) {
2813 // Disable clamshell sleep until system has completed full wake.
2814 // This prevents a system sleep request (due to a clamshell close)
2815 // from being queued until the end of system full wake - even if
2816 // other clamshell disable bits outside of our control is wrong.
2817 setClamShellSleepDisable(true, kClamshellSleepDisableInternal);
2818 }
2819 #endif
2820
2821 // Log the last known clamshell state before system sleep
2822 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
2823 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask,
2824 desktopMode, acAdaptorConnected);
2825 }
2826
2827 clock_get_calendar_absolute_and_microtime(&secs, &microsecs, &now);
2828 logtime(secs);
2829 gIOLastSleepTime.tv_sec = secs;
2830 gIOLastSleepTime.tv_usec = microsecs;
2831 if (!_aotLastWakeTime) {
2832 gIOLastUserSleepTime = gIOLastSleepTime;
2833 }
2834
2835 gIOLastWakeTime.tv_sec = 0;
2836 gIOLastWakeTime.tv_usec = 0;
2837 gIOLastSleepAbsTime = now;
2838
2839 if (wake2DarkwakeDelay && sleepDelaysReport) {
2840 clock_sec_t wake2DarkwakeSecs, darkwake2SleepSecs;
2841 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2842
2843 SUB_ABSOLUTETIME(&now, &ts_sleepStart);
2844 absolutetime_to_microtime(now, &darkwake2SleepSecs, &microsecs);
2845 absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, &microsecs);
2846 HISTREPORT_TALLYVALUE(sleepDelaysReport,
2847 (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
2848
2849 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
2850 wake2DarkwakeDelay = 0;
2851 }
2852 #if HIBERNATION
2853 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2854
2855 IOHibernateSystemHasSlept();
2856
2857 evaluateSystemSleepPolicyFinal();
2858 #else
2859 LOG("System Sleep\n");
2860 #endif
2861 if (thermalWarningState) {
2862 OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
2863 if (event) {
2864 systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
2865 }
2866 }
2867 assertOnWakeSecs = 0;
2868 lowBatteryCondition = false;
2869 thermalEmergencyState = false;
2870
2871 #if DEVELOPMENT || DEBUG
2872 extern int g_should_log_clock_adjustments;
2873 if (g_should_log_clock_adjustments) {
2874 clock_sec_t secs = 0;
2875 clock_usec_t microsecs = 0;
2876 uint64_t now_b = mach_absolute_time();
2877
2878 secs = 0;
2879 microsecs = 0;
2880 PEGetUTCTimeOfDay(&secs, &microsecs);
2881
2882 uint64_t now_a = mach_absolute_time();
2883 os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2884 __func__, (unsigned long)secs, microsecs, now_b, now_a);
2885 }
2886 #endif
2887
2888 getPlatform()->sleepKernel();
2889
2890 // The CPU(s) are off at this point,
2891 // Code will resume execution here upon wake.
2892
2893 clock_get_uptime(&gIOLastWakeAbsTime);
2894 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
2895 _highestCapability = 0;
2896
2897 #if HIBERNATION
2898 IOHibernateSystemWake();
2899 #endif
2900
2901 // sleep transition complete
2902 gSleepOrShutdownPending = 0;
2903
2904 // trip the reset of the calendar clock
2905 clock_wakeup_calendar();
2906 clock_get_calendar_microtime(&secs, &microsecs);
2907 gIOLastWakeTime.tv_sec = secs;
2908 gIOLastWakeTime.tv_usec = microsecs;
2909
2910 // aot
2911 if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
2912 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
2913 secs = 0;
2914 microsecs = 0;
2915 PEGetUTCTimeOfDay(&secs, &microsecs);
2916 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2917 IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2918 _aotMetrics->sleepCount++;
2919 _aotLastWakeTime = gIOLastWakeAbsTime;
2920 if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
2921 _aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
2922 = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
2923 _aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
2924 = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
2925 }
2926
2927 if (_aotTestTime) {
2928 if (_aotWakeTimeUTC <= secs) {
2929 _aotTestTime = _aotTestTime + _aotTestInterval;
2930 }
2931 setWakeTime(_aotTestTime);
2932 }
2933 }
2934
2935 #if HIBERNATION
2936 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
2937 #endif
2938
2939 lastSleepReason = 0;
2940
2941 lastDebugWakeSeconds = _debugWakeSeconds;
2942 _debugWakeSeconds = 0;
2943 _scheduledAlarmMask = 0;
2944 _nextScheduledAlarmType = NULL;
2945
2946 darkWakeExit = false;
2947 darkWakePowerClamped = false;
2948 darkWakePostTickle = false;
2949 darkWakeHibernateError = false;
2950 darkWakeToSleepASAP = true;
2951 darkWakeLogClamp = true;
2952 sleepTimerMaintenance = false;
2953 sleepToStandby = false;
2954 wranglerTickled = false;
2955 userWasActive = false;
2956 isRTCAlarmWake = false;
2957 clamshellIgnoreClose = false;
2958 fullWakeReason = kFullWakeReasonNone;
2959
2960 #if defined(__i386__) || defined(__x86_64__)
2961 kdebugTrace(kPMLogSystemWake, 0, 0, 0);
2962
2963 OSSharedPtr<OSObject> wakeTypeProp = copyProperty(kIOPMRootDomainWakeTypeKey);
2964 OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey);
2965 OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get());
2966 OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get());
2967
2968 if (wakeReason && (wakeReason->getLength() >= 2) &&
2969 gWakeReasonString[0] == '\0') {
2970 WAKEEVENT_LOCK();
2971 // Until the platform driver can claim its wake reasons
2972 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
2973 sizeof(gWakeReasonString));
2974 WAKEEVENT_UNLOCK();
2975 }
2976
2977 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
2978 lowBatteryCondition = true;
2979 darkWakeMaintenance = true;
2980 } else {
2981 #if HIBERNATION
2982 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
2983 OSNumber * hibOptions = OSDynamicCast( OSNumber, hibOptionsProp.get());
2984 if (hibernateAborted || ((hibOptions &&
2985 !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
2986 // Hibernate aborted, or EFI brought up graphics
2987 darkWakeExit = true;
2988 if (hibernateAborted) {
2989 DLOG("Hibernation aborted\n");
2990 } else {
2991 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
2992 }
2993 } else
2994 #endif
2995 if (wakeType && (
2996 wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
2997 wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
2998 // User wake or RTC alarm
2999 darkWakeExit = true;
3000 if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
3001 isRTCAlarmWake = true;
3002 }
3003 } else if (wakeType &&
3004 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
3005 // SMC standby timer trumps SleepX
3006 darkWakeMaintenance = true;
3007 sleepTimerMaintenance = true;
3008 } else if ((lastDebugWakeSeconds != 0) &&
3009 ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
3010 // SleepX before maintenance
3011 darkWakeExit = true;
3012 } else if (wakeType &&
3013 wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
3014 darkWakeMaintenance = true;
3015 } else if (wakeType &&
3016 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
3017 darkWakeMaintenance = true;
3018 darkWakeSleepService = true;
3019 #if HIBERNATION
3020 if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3021 sleepToStandby = true;
3022 }
3023 #endif
3024 } else if (wakeType &&
3025 wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3026 darkWakeMaintenance = true;
3027 darkWakeHibernateError = true;
3028 } else {
3029 // Unidentified wake source, resume to full wake if debug
3030 // alarm is pending.
3031
3032 if (lastDebugWakeSeconds &&
3033 (!wakeReason || wakeReason->isEqualTo(""))) {
3034 darkWakeExit = true;
3035 }
3036 }
3037 }
3038
3039 if (darkWakeExit) {
3040 darkWakeToSleepASAP = false;
3041 fullWakeReason = kFullWakeReasonLocalUser;
3042 reportUserInput();
3043 } else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
3044 handleSetDisplayPowerOn(true);
3045 } else if (!darkWakeMaintenance) {
3046 // Early/late tickle for non-maintenance wake.
3047 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) {
3048 darkWakePostTickle = true;
3049 }
3050 }
3051 #else /* !__i386__ && !__x86_64__ */
3052 timeSinceReset = ml_get_time_since_reset();
3053 kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3054
3055 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) {
3056 wranglerTickled = true;
3057 fullWakeReason = kFullWakeReasonLocalUser;
3058 requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3059 } else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
3060 isRTCAlarmWake = true;
3061 fullWakeReason = kFullWakeReasonLocalUser;
3062 requestUserActive(this, "RTC debug alarm");
3063 }
3064
3065 // stay awake for at least 30 seconds
3066 startIdleSleepTimer(30);
3067 #endif
3068 sleepCnt++;
3069
3070 thread_call_enter(updateConsoleUsersEntry);
3071
3072 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
3073 break;
3074 }
3075 #if !__i386__ && !__x86_64__
3076 case ON_STATE:
3077 case AOT_STATE:
3078 {
3079 DLOG("Force re-evaluating aggressiveness\n");
3080 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3081 pmPowerStateQueue->submitPowerEvent(
3082 kPowerEventPolicyStimulus,
3083 (void *) kStimulusNoIdleSleepPreventers );
3084
3085 // After changing to ON_STATE, invalidate any previously queued
3086 // request to change to a state less than ON_STATE. This isn't
3087 // necessary for AOT_STATE or if the device has only one running
3088 // state since the changePowerStateToPriv() issued at the tail
3089 // end of SLEEP_STATE case should take care of that.
3090 if (getPowerState() == ON_STATE) {
3091 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake);
3092 }
3093 break;
3094 }
3095 #endif /* !__i386__ && !__x86_64__ */
3096 }
3097 notifierThread = NULL;
3098 }
3099
3100 //******************************************************************************
3101 // requestPowerDomainState
3102 //
3103 // Extend implementation in IOService. Running on PM work loop thread.
3104 //******************************************************************************
3105
3106 IOReturn
3107 IOPMrootDomain::requestPowerDomainState(
3108 IOPMPowerFlags childDesire,
3109 IOPowerConnection * childConnection,
3110 unsigned long specification )
3111 {
3112 // Idle and system sleep prevention flags affects driver desire.
3113 // Children desire are irrelevant so they are cleared.
3114
3115 return super::requestPowerDomainState(0, childConnection, specification);
3116 }
3117
3118
3119 static void
3120 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3121 {
3122 if (!preventers->getCount()) {
3123 return;
3124 }
3125
3126 char *buf_iter = buf + strlen(buf);
3127 char *buf_end = buf + buf_size;
3128
3129 OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3130 OSObject *obj = NULL;
3131
3132 while ((obj = iterator->getNextObject())) {
3133 IOService *srv = OSDynamicCast(IOService, obj);
3134 if (buf_iter < buf_end) {
3135 buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName());
3136 } else {
3137 DLOG("Print buffer exhausted for sleep preventers list\n");
3138 break;
3139 }
3140 }
3141 }
3142
3143 //******************************************************************************
3144 // updatePreventIdleSleepList
3145 //
3146 // Called by IOService on PM work loop.
3147 // Returns true if PM policy recognized the driver's desire to prevent idle
3148 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3149 //******************************************************************************
3150
3151 bool
3152 IOPMrootDomain::updatePreventIdleSleepList(
3153 IOService * service, bool addNotRemove)
3154 {
3155 unsigned int oldCount;
3156
3157 oldCount = idleSleepPreventersCount();
3158 return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3159 }
3160
3161 bool
3162 IOPMrootDomain::updatePreventIdleSleepListInternal(
3163 IOService * service, bool addNotRemove, unsigned int oldCount)
3164 {
3165 unsigned int newCount;
3166
3167 ASSERT_GATED();
3168
3169 #if defined(XNU_TARGET_OS_OSX)
3170 // Only the display wrangler and no-idle-sleep kernel assertions
3171 // can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3172 // reported by drivers in their power state table is ignored.
3173 if (service && (service != wrangler) && (service != this)) {
3174 return false;
3175 }
3176 #endif
3177
3178 if (service) {
3179 if (addNotRemove) {
3180 preventIdleSleepList->setObject(service);
3181 DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3182 service->getName(), preventIdleSleepList->getCount());
3183 } else if (preventIdleSleepList->member(service)) {
3184 preventIdleSleepList->removeObject(service);
3185 DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3186 service->getName(), preventIdleSleepList->getCount());
3187 }
3188
3189 if (preventIdleSleepList->getCount()) {
3190 char buf[256] = "Idle Sleep Preventers:";
3191 makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3192 DLOG("%s\n", buf);
3193 }
3194 }
3195
3196 newCount = idleSleepPreventersCount();
3197
3198 if ((oldCount == 0) && (newCount != 0)) {
3199 // Driver added to empty prevent list.
3200 // Update the driver desire to prevent idle sleep.
3201 // Driver desire does not prevent demand sleep.
3202
3203 changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent);
3204 } else if ((oldCount != 0) && (newCount == 0)) {
3205 // Last driver removed from prevent list.
3206 // Drop the driver clamp to allow idle sleep.
3207
3208 changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3209 evaluatePolicy( kStimulusNoIdleSleepPreventers );
3210 }
3211 messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3212 &newCount, sizeof(newCount));
3213
3214 #if defined(XNU_TARGET_OS_OSX)
3215 if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
3216 DLOG("Cannot cancel idle sleep\n");
3217 return false; // do not idle-cancel
3218 }
3219 #endif
3220
3221 return true;
3222 }
3223
3224 //******************************************************************************
3225 // startSpinDump
3226 //******************************************************************************
3227
3228 void
3229 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3230 {
3231 messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3232 }
3233
3234 //******************************************************************************
3235 // preventSystemSleepListUpdate
3236 //
3237 // Called by IOService on PM work loop.
3238 //******************************************************************************
3239
3240 void
3241 IOPMrootDomain::updatePreventSystemSleepList(
3242 IOService * service, bool addNotRemove )
3243 {
3244 unsigned int oldCount, newCount;
3245
3246 ASSERT_GATED();
3247 if (this == service) {
3248 return;
3249 }
3250
3251 oldCount = preventSystemSleepList->getCount();
3252 if (addNotRemove) {
3253 preventSystemSleepList->setObject(service);
3254 DLOG("Added %s to system sleep preventers list (Total %u)\n",
3255 service->getName(), preventSystemSleepList->getCount());
3256 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
3257 AbsoluteTime now;
3258 clock_usec_t microsecs;
3259 clock_get_uptime(&now);
3260 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3261 absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
3262 if (assertOnWakeReport) {
3263 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3264 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3265 }
3266 }
3267 } else if (preventSystemSleepList->member(service)) {
3268 preventSystemSleepList->removeObject(service);
3269 DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3270 service->getName(), preventSystemSleepList->getCount());
3271
3272 if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
3273 // Lost all system sleep preventers.
3274 // Send stimulus if system sleep was blocked, and is in dark wake.
3275 evaluatePolicy( kStimulusDarkWakeEvaluate );
3276 }
3277 }
3278
3279 newCount = preventSystemSleepList->getCount();
3280 if (newCount) {
3281 char buf[256] = "System Sleep Preventers:";
3282 makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3283 DLOG("%s\n", buf);
3284 }
3285
3286 messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3287 &newCount, sizeof(newCount));
3288 }
3289
3290 void
3291 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3292 {
3293 OSSharedPtr<OSCollectionIterator> iterator;
3294 OSObject *object = NULL;
3295 OSSharedPtr<OSArray> array;
3296
3297 if (!gIOPMWorkLoop->inGate()) {
3298 gIOPMWorkLoop->runAction(
3299 OSMemberFunctionCast(IOWorkLoop::Action, this,
3300 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3301 this, (void *)idleSleepList, (void *)systemSleepList);
3302 return;
3303 }
3304
3305 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3306 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3307 array = OSArray::withCapacity(5);
3308
3309 if (iterator && array) {
3310 while ((object = iterator->getNextObject())) {
3311 IOService *service = OSDynamicCast(IOService, object);
3312 if (service) {
3313 OSSharedPtr<const OSSymbol> name = service->copyName();
3314 if (name) {
3315 array->setObject(name.get());
3316 }
3317 }
3318 }
3319 }
3320 *idleSleepList = array.detach();
3321 }
3322
3323 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3324 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3325 array = OSArray::withCapacity(5);
3326
3327 if (iterator && array) {
3328 while ((object = iterator->getNextObject())) {
3329 IOService *service = OSDynamicCast(IOService, object);
3330 if (service) {
3331 OSSharedPtr<const OSSymbol> name = service->copyName();
3332 if (name) {
3333 array->setObject(name.get());
3334 }
3335 }
3336 }
3337 }
3338 *systemSleepList = array.detach();
3339 }
3340 }
3341
3342 void
3343 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3344 {
3345 OSSharedPtr<OSCollectionIterator> iterator;
3346 OSObject *object = NULL;
3347 OSSharedPtr<OSArray> array;
3348
3349 if (!gIOPMWorkLoop->inGate()) {
3350 gIOPMWorkLoop->runAction(
3351 OSMemberFunctionCast(IOWorkLoop::Action, this,
3352 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3353 this, (void *)idleSleepList, (void *)systemSleepList);
3354 return;
3355 }
3356
3357 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3358 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3359 array = OSArray::withCapacity(5);
3360
3361 if (iterator && array) {
3362 while ((object = iterator->getNextObject())) {
3363 IOService *service = OSDynamicCast(IOService, object);
3364 if (service) {
3365 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3366 OSSharedPtr<const OSSymbol> name = service->copyName();
3367 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3368 if (dict && name && id) {
3369 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3370 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3371 array->setObject(dict.get());
3372 }
3373 }
3374 }
3375 }
3376 *idleSleepList = array.detach();
3377 }
3378
3379 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3380 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3381 array = OSArray::withCapacity(5);
3382
3383 if (iterator && array) {
3384 while ((object = iterator->getNextObject())) {
3385 IOService *service = OSDynamicCast(IOService, object);
3386 if (service) {
3387 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3388 OSSharedPtr<const OSSymbol> name = service->copyName();
3389 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3390 if (dict && name && id) {
3391 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3392 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3393 array->setObject(dict.get());
3394 }
3395 }
3396 }
3397 }
3398 *systemSleepList = array.detach();
3399 }
3400 }
3401
3402 //******************************************************************************
3403 // tellChangeDown
3404 //
3405 // Override the superclass implementation to send a different message type.
3406 //******************************************************************************
3407
3408 bool
3409 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3410 {
3411 DLOG("tellChangeDown %s->%s\n",
3412 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3413
3414 if (SLEEP_STATE == stateNum) {
3415 // Legacy apps were already told in the full->dark transition
3416 if (!ignoreTellChangeDown) {
3417 tracePoint( kIOPMTracePointSleepApplications );
3418 } else {
3419 tracePoint( kIOPMTracePointSleepPriorityClients );
3420 }
3421 }
3422
3423 if (!ignoreTellChangeDown) {
3424 userActivityAtSleep = userActivityCount;
3425 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3426
3427 if (SLEEP_STATE == stateNum) {
3428 hibernateAborted = false;
3429
3430 // Direct callout into OSKext so it can disable kext unloads
3431 // during sleep/wake to prevent deadlocks.
3432 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3433
3434 IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3435
3436 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3437 // But tellClientsWithResponse() must be called for both.
3438 ignoreTellChangeDown = true;
3439 }
3440 }
3441
3442 return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3443 }
3444
3445 //******************************************************************************
3446 // askChangeDown
3447 //
3448 // Override the superclass implementation to send a different message type.
3449 // This must be idle sleep since we don't ask during any other power change.
3450 //******************************************************************************
3451
3452 bool
3453 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3454 {
3455 DLOG("askChangeDown %s->%s\n",
3456 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3457
3458 // Don't log for dark wake entry
3459 if (kSystemTransitionSleep == _systemTransitionType) {
3460 tracePoint( kIOPMTracePointSleepApplications );
3461 }
3462
3463 return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3464 }
3465
3466 //******************************************************************************
3467 // askChangeDownDone
3468 //
3469 // An opportunity for root domain to cancel the power transition,
3470 // possibily due to an assertion created by powerd in response to
3471 // kIOMessageCanSystemSleep.
3472 //
3473 // Idle sleep:
3474 // full -> dark wake transition
3475 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3476 // 2. askChangeDownDone()
3477 // dark -> sleep transition
3478 // 1. Notify powerd with kIOMessageCanSystemSleep
3479 // 2. askChangeDownDone()
3480 //
3481 // Demand sleep:
3482 // full -> dark wake transition
3483 // 1. Notify powerd with kIOMessageCanSystemSleep
3484 // 2. askChangeDownDone()
3485 // dark -> sleep transition
3486 // 1. Notify powerd with kIOMessageCanSystemSleep
3487 // 2. askChangeDownDone()
3488 //******************************************************************************
3489
3490 void
3491 IOPMrootDomain::askChangeDownDone(
3492 IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3493 {
3494 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3495 *inOutChangeFlags, *cancel,
3496 _systemTransitionType,
3497 _currentCapability, _pendingCapability);
3498
3499 if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
3500 // Dark->Sleep transition.
3501 // Check if there are any deny sleep assertions.
3502 // lastSleepReason already set by handleOurPowerChangeStart()
3503
3504 if (!checkSystemCanSleep(lastSleepReason)) {
3505 // Cancel dark wake to sleep transition.
3506 // Must re-scan assertions upon entering dark wake.
3507
3508 *cancel = true;
3509 DLOG("cancel dark->sleep\n");
3510 }
3511 if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3512 uint64_t now = mach_continuous_time();
3513 if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3514 && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3515 *cancel = true;
3516 IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3517 }
3518 }
3519 }
3520 }
3521
3522 //******************************************************************************
3523 // systemDidNotSleep
3524 //
3525 // Work common to both canceled or aborted sleep.
3526 //******************************************************************************
3527
3528 void
3529 IOPMrootDomain::systemDidNotSleep( void )
3530 {
3531 // reset console lock state
3532 thread_call_enter(updateConsoleUsersEntry);
3533
3534 if (idleSleepEnabled) {
3535 if (!wrangler) {
3536 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3537 startIdleSleepTimer(kIdleSleepRetryInterval);
3538 #else
3539 startIdleSleepTimer(idleSeconds);
3540 #endif
3541 } else if (!userIsActive) {
3542 // Manually start the idle sleep timer besides waiting for
3543 // the user to become inactive.
3544 startIdleSleepTimer(kIdleSleepRetryInterval);
3545 }
3546 }
3547
3548 preventTransitionToUserActive(false);
3549 IOService::setAdvisoryTickleEnable( true );
3550
3551 // After idle revert and cancel, send a did-change message to powerd
3552 // to balance the previous will-change message. Kernel clients do not
3553 // need this since sleep cannot be canceled once they are notified.
3554
3555 if (toldPowerdCapWillChange && systemCapabilityNotifier &&
3556 (_pendingCapability != _currentCapability) &&
3557 ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
3558 // Differs from a real capability gain change where notifyRef != 0,
3559 // but it is zero here since no response is expected.
3560
3561 IOPMSystemCapabilityChangeParameters params;
3562
3563 bzero(&params, sizeof(params));
3564 params.fromCapabilities = _pendingCapability;
3565 params.toCapabilities = _currentCapability;
3566 params.changeFlags = kIOPMSystemCapabilityDidChange;
3567
3568 DLOG("MESG cap %x->%x did change\n",
3569 params.fromCapabilities, params.toCapabilities);
3570 messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3571 &params, sizeof(params));
3572 }
3573 }
3574
3575 //******************************************************************************
3576 // tellNoChangeDown
3577 //
3578 // Notify registered applications and kernel clients that we are not dropping
3579 // power.
3580 //
3581 // We override the superclass implementation so we can send a different message
3582 // type to the client or application being notified.
3583 //
3584 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3585 //******************************************************************************
3586
3587 void
3588 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3589 {
3590 DLOG("tellNoChangeDown %s->%s\n",
3591 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3592
3593 // Sleep canceled, clear the sleep trace point.
3594 tracePoint(kIOPMTracePointSystemUp);
3595
3596 systemDidNotSleep();
3597 return tellClients( kIOMessageSystemWillNotSleep );
3598 }
3599
3600 //******************************************************************************
3601 // tellChangeUp
3602 //
3603 // Notify registered applications and kernel clients that we are raising power.
3604 //
3605 // We override the superclass implementation so we can send a different message
3606 // type to the client or application being notified.
3607 //******************************************************************************
3608
3609 void
3610 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3611 {
3612 DLOG("tellChangeUp %s->%s\n",
3613 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3614
3615 ignoreTellChangeDown = false;
3616
3617 if (stateNum == ON_STATE) {
3618 // Direct callout into OSKext so it can disable kext unloads
3619 // during sleep/wake to prevent deadlocks.
3620 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3621
3622 // Notify platform that sleep was cancelled or resumed.
3623 getPlatform()->callPlatformFunction(
3624 sleepMessagePEFunction.get(), false,
3625 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3626 NULL, NULL, NULL);
3627
3628 if (getPowerState() == ON_STATE) {
3629 // Sleep was cancelled by idle cancel or revert
3630 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
3631 // rdar://problem/50363791
3632 // If system is in dark wake and sleep is cancelled, do not
3633 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3634 // priority clients. They haven't yet seen a SystemWillSleep
3635 // message before the cancellation. So make sure the kernel
3636 // client bit is cleared in _systemMessageClientMask before
3637 // invoking the tellClients() below. This bit may have been
3638 // set by handleOurPowerChangeStart() anticipating a successful
3639 // sleep and setting the filter mask ahead of time allows the
3640 // SystemWillSleep message to go through.
3641 _systemMessageClientMask &= ~kSystemMessageClientKernel;
3642 }
3643
3644 systemDidNotSleep();
3645 tellClients( kIOMessageSystemWillPowerOn );
3646 }
3647
3648 tracePoint( kIOPMTracePointWakeApplications );
3649 tellClients( kIOMessageSystemHasPoweredOn );
3650 }
3651 }
3652
3653 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3654 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3655 ((params)->fromCapabilities & (flag)) && \
3656 (((params)->toCapabilities & (flag)) == 0))
3657
3658 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3659 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3660 ((params)->toCapabilities & (flag)) && \
3661 (((params)->fromCapabilities & (flag)) == 0))
3662
3663 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3664 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3665 ((params)->fromCapabilities & (flag)) && \
3666 (((params)->toCapabilities & (flag)) == 0))
3667
3668 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3669 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3670 ((params)->toCapabilities & (flag)) && \
3671 (((params)->fromCapabilities & (flag)) == 0))
3672
3673 //******************************************************************************
3674 // sysPowerDownHandler
3675 //
3676 // Perform a vfs sync before system sleep.
3677 //******************************************************************************
3678
3679 IOReturn
3680 IOPMrootDomain::sysPowerDownHandler(
3681 void * target, void * refCon,
3682 UInt32 messageType, IOService * service,
3683 void * messageArgs, vm_size_t argSize )
3684 {
3685 static UInt32 lastSystemMessageType = 0;
3686 IOReturn ret = 0;
3687
3688 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3689
3690 // rdar://problem/50363791
3691 // Sanity check to make sure the SystemWill/Has message types are
3692 // received in the expected order for all kernel priority clients.
3693 if (messageType == kIOMessageSystemWillSleep ||
3694 messageType == kIOMessageSystemWillPowerOn ||
3695 messageType == kIOMessageSystemHasPoweredOn) {
3696 switch (messageType) {
3697 case kIOMessageSystemWillPowerOn:
3698 assert(lastSystemMessageType == kIOMessageSystemWillSleep);
3699 break;
3700 case kIOMessageSystemHasPoweredOn:
3701 assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3702 break;
3703 }
3704
3705 lastSystemMessageType = messageType;
3706 }
3707
3708 if (!gRootDomain) {
3709 return kIOReturnUnsupported;
3710 }
3711
3712 if (messageType == kIOMessageSystemCapabilityChange) {
3713 IOPMSystemCapabilityChangeParameters * params =
3714 (IOPMSystemCapabilityChangeParameters *) messageArgs;
3715
3716 // Interested applications have been notified of an impending power
3717 // change and have acked (when applicable).
3718 // This is our chance to save whatever state we can before powering
3719 // down.
3720 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3721 // via callout
3722
3723 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3724 params->fromCapabilities, params->toCapabilities,
3725 params->changeFlags);
3726
3727 if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3728 // We will ack within 20 seconds
3729 params->maxWaitForReply = 20 * 1000 * 1000;
3730
3731 #if HIBERNATION
3732 gRootDomain->evaluateSystemSleepPolicyEarly();
3733
3734 // add in time we could spend freeing pages
3735 if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3736 params->maxWaitForReply = kCapabilityClientMaxWait;
3737 }
3738 DLOG("sysPowerDownHandler max wait %d s\n",
3739 (int) (params->maxWaitForReply / 1000 / 1000));
3740 #endif
3741
3742 // Notify platform that sleep has begun, after the early
3743 // sleep policy evaluation.
3744 getPlatform()->callPlatformFunction(
3745 sleepMessagePEFunction.get(), false,
3746 (void *)(uintptr_t) kIOMessageSystemWillSleep,
3747 NULL, NULL, NULL);
3748
3749 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3750 // Purposely delay the ack and hope that shutdown occurs quickly.
3751 // Another option is not to schedule the thread and wait for
3752 // ack timeout...
3753 AbsoluteTime deadline;
3754 clock_interval_to_deadline( 30, kSecondScale, &deadline );
3755 thread_call_enter1_delayed(
3756 gRootDomain->diskSyncCalloutEntry,
3757 (thread_call_param_t)(uintptr_t) params->notifyRef,
3758 deadline );
3759 } else {
3760 thread_call_enter1(
3761 gRootDomain->diskSyncCalloutEntry,
3762 (thread_call_param_t)(uintptr_t) params->notifyRef);
3763 }
3764 }
3765 #if HIBERNATION
3766 else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
3767 // We will ack within 110 seconds
3768 params->maxWaitForReply = 110 * 1000 * 1000;
3769
3770 thread_call_enter1(
3771 gRootDomain->diskSyncCalloutEntry,
3772 (thread_call_param_t)(uintptr_t) params->notifyRef);
3773 }
3774 #endif
3775 ret = kIOReturnSuccess;
3776 }
3777
3778 return ret;
3779 }
3780
3781 //******************************************************************************
3782 // handleQueueSleepWakeUUID
3783 //
3784 // Called from IOPMrootDomain when we're initiating a sleep,
3785 // or indirectly from PM configd when PM decides to clear the UUID.
3786 // PM clears the UUID several minutes after successful wake from sleep,
3787 // so that we might associate App spindumps with the immediately previous
3788 // sleep/wake.
3789 //
3790 // @param obj has a retain on it. We're responsible for releasing that retain.
3791 //******************************************************************************
3792
3793 void
3794 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
3795 {
3796 OSSharedPtr<OSString> str;
3797
3798 if (kOSBooleanFalse == obj) {
3799 handlePublishSleepWakeUUID(false);
3800 } else {
3801 str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
3802 if (str) {
3803 // This branch caches the UUID for an upcoming sleep/wake
3804 queuedSleepWakeUUIDString = str;
3805 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
3806 }
3807 }
3808 }
3809 //******************************************************************************
3810 // handlePublishSleepWakeUUID
3811 //
3812 // Called from IOPMrootDomain when we're initiating a sleep,
3813 // or indirectly from PM configd when PM decides to clear the UUID.
3814 // PM clears the UUID several minutes after successful wake from sleep,
3815 // so that we might associate App spindumps with the immediately previous
3816 // sleep/wake.
3817 //******************************************************************************
3818
3819 void
3820 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
3821 {
3822 ASSERT_GATED();
3823
3824 /*
3825 * Clear the current UUID
3826 */
3827 if (gSleepWakeUUIDIsSet) {
3828 DLOG("SleepWake UUID cleared\n");
3829
3830 gSleepWakeUUIDIsSet = false;
3831
3832 removeProperty(kIOPMSleepWakeUUIDKey);
3833 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
3834 }
3835
3836 /*
3837 * Optionally, publish a new UUID
3838 */
3839 if (queuedSleepWakeUUIDString && shouldPublish) {
3840 OSSharedPtr<OSString> publishThisUUID;
3841
3842 publishThisUUID = queuedSleepWakeUUIDString;
3843
3844 if (publishThisUUID) {
3845 setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
3846 }
3847
3848 gSleepWakeUUIDIsSet = true;
3849 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
3850
3851 queuedSleepWakeUUIDString.reset();
3852 }
3853 }
3854
3855 //******************************************************************************
3856 // IOPMGetSleepWakeUUIDKey
3857 //
3858 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3859 // To get the full key -- a C string -- the buffer must large enough for
3860 // the end-of-string character.
3861 // The key is expected to be an UUID string
3862 //******************************************************************************
3863
3864 extern "C" bool
3865 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
3866 {
3867 if (!gSleepWakeUUIDIsSet) {
3868 return false;
3869 }
3870
3871 if (buffer != NULL) {
3872 OSSharedPtr<OSString> string =
3873 OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
3874
3875 if (!string) {
3876 *buffer = '\0';
3877 } else {
3878 strlcpy(buffer, string->getCStringNoCopy(), buf_len);
3879 }
3880 }
3881
3882 return true;
3883 }
3884
3885 //******************************************************************************
3886 // lowLatencyAudioNotify
3887 //
3888 // Used to send an update about low latency audio activity to interested
3889 // clients. To keep the overhead minimal the OSDictionary used here
3890 // is initialized at boot.
3891 //******************************************************************************
3892
3893 void
3894 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
3895 {
3896 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
3897 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
3898 lowLatencyAudioNotifyTimestampVal->setValue(time);
3899 lowLatencyAudioNotifyStateVal->setValue(state);
3900 setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
3901 } else {
3902 DLOG("LowLatencyAudioNotify error\n");
3903 }
3904 return;
3905 }
3906
3907 //******************************************************************************
3908 // IOPMrootDomainRTNotifier
3909 //
3910 // Used by performance controller to update the timestamp and state associated
3911 // with low latency audio activity in the system.
3912 //******************************************************************************
3913
3914 extern "C" void
3915 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
3916 {
3917 gRootDomain->lowLatencyAudioNotify(time, state);
3918 return;
3919 }
3920
3921 //******************************************************************************
3922 // initializeBootSessionUUID
3923 //
3924 // Initialize the boot session uuid at boot up and sets it into registry.
3925 //******************************************************************************
3926
3927 void
3928 IOPMrootDomain::initializeBootSessionUUID(void)
3929 {
3930 uuid_t new_uuid;
3931 uuid_string_t new_uuid_string;
3932
3933 uuid_generate(new_uuid);
3934 uuid_unparse_upper(new_uuid, new_uuid_string);
3935 memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
3936
3937 setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
3938 }
3939
3940 //******************************************************************************
3941 // Root domain uses the private and tagged changePowerState methods for
3942 // tracking and logging purposes.
3943 //******************************************************************************
3944
3945 #define REQUEST_TAG_TO_REASON(x) ((uint16_t)x)
3946
3947 static uint32_t
3948 nextRequestTag( IOPMRequestTag tag )
3949 {
3950 static SInt16 msb16 = 1;
3951 uint16_t id = OSAddAtomic16(1, &msb16);
3952 return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
3953 }
3954
3955 // TODO: remove this shim function and exported symbol
3956 IOReturn
3957 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
3958 {
3959 return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
3960 }
3961
3962 // TODO: remove this shim function and exported symbol
3963 IOReturn
3964 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
3965 {
3966 return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
3967 }
3968
3969 IOReturn
3970 IOPMrootDomain::changePowerStateWithOverrideTo(
3971 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
3972 {
3973 uint32_t tag = nextRequestTag(reason);
3974 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
3975
3976 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
3977 return kIOReturnUnsupported;
3978 }
3979
3980 return super::changePowerStateWithOverrideTo(ordinal, tag);
3981 }
3982
3983 IOReturn
3984 IOPMrootDomain::changePowerStateWithTagTo(
3985 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
3986 {
3987 uint32_t tag = nextRequestTag(reason);
3988 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
3989
3990 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
3991 return kIOReturnUnsupported;
3992 }
3993
3994 return super::changePowerStateWithTagTo(ordinal, tag);
3995 }
3996
3997 IOReturn
3998 IOPMrootDomain::changePowerStateWithTagToPriv(
3999 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4000 {
4001 uint32_t tag = nextRequestTag(reason);
4002 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4003
4004 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4005 return kIOReturnUnsupported;
4006 }
4007
4008 return super::changePowerStateWithTagToPriv(ordinal, tag);
4009 }
4010
4011 //******************************************************************************
4012 // activity detect
4013 //
4014 //******************************************************************************
4015
4016 bool
4017 IOPMrootDomain::activitySinceSleep(void)
4018 {
4019 return userActivityCount != userActivityAtSleep;
4020 }
4021
4022 bool
4023 IOPMrootDomain::abortHibernation(void)
4024 {
4025 #if __arm64__
4026 // don't allow hibernation to be aborted on ARM due to user activity
4027 // since once ApplePMGR decides we're hibernating, we can't turn back
4028 // see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4029 return false;
4030 #else
4031 bool ret = activitySinceSleep();
4032
4033 if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4034 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4035 hibernateAborted = true;
4036 }
4037 return ret;
4038 #endif
4039 }
4040
4041 extern "C" int
4042 hibernate_should_abort(void)
4043 {
4044 if (gRootDomain) {
4045 return gRootDomain->abortHibernation();
4046 } else {
4047 return 0;
4048 }
4049 }
4050
4051 //******************************************************************************
4052 // willNotifyPowerChildren
4053 //
4054 // Called after all interested drivers have all acknowledged the power change,
4055 // but before any power children is informed. Dispatched though a thread call,
4056 // so it is safe to perform work that might block on a sleeping disk. PM state
4057 // machine (not thread) will block w/o timeout until this function returns.
4058 //******************************************************************************
4059
4060 void
4061 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4062 {
4063 OSSharedPtr<OSDictionary> dict;
4064 OSSharedPtr<OSNumber> secs;
4065
4066 if (SLEEP_STATE == newPowerState) {
4067 notifierThread = current_thread();
4068 if (!tasksSuspended) {
4069 AbsoluteTime deadline;
4070 tasksSuspended = TRUE;
4071 updateTasksSuspend();
4072
4073 clock_interval_to_deadline(10, kSecondScale, &deadline);
4074 #if defined(XNU_TARGET_OS_OSX)
4075 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
4076 #endif /* defined(XNU_TARGET_OS_OSX) */
4077 }
4078
4079 _aotReadyToFullWake = false;
4080 #if 0
4081 if (_aotLingerTime) {
4082 uint64_t deadline;
4083 IOLog("aot linger no return\n");
4084 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
4085 clock_delay_until(deadline);
4086 }
4087 #endif
4088 if (!_aotMode) {
4089 _aotTestTime = 0;
4090 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4091 if (_aotMetrics) {
4092 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4093 }
4094 } else if (!_aotNow && !_debugWakeSeconds) {
4095 _aotNow = true;
4096 _aotExit = false;
4097 _aotPendingFlags = 0;
4098 _aotTasksSuspended = true;
4099 _aotLastWakeTime = 0;
4100 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4101 if (kIOPMAOTModeCycle & _aotMode) {
4102 clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
4103 _aotTestTime = mach_continuous_time() + _aotTestInterval;
4104 setWakeTime(_aotTestTime);
4105 }
4106 uint32_t lingerSecs;
4107 if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
4108 lingerSecs = 0;
4109 }
4110 clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
4111 clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
4112 clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
4113 }
4114
4115 #if HIBERNATION
4116 IOHibernateSystemSleep();
4117 IOHibernateIOKitSleep();
4118 #endif
4119 if (gRootDomain->activitySinceSleep()) {
4120 dict = OSDictionary::withCapacity(1);
4121 secs = OSNumber::withNumber(1, 32);
4122
4123 if (dict && secs) {
4124 dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4125 gRootDomain->setProperties(dict.get());
4126 MSG("Reverting sleep with relative wake\n");
4127 }
4128 }
4129
4130 notifierThread = NULL;
4131 }
4132 }
4133
4134 //******************************************************************************
4135 // willTellSystemCapabilityDidChange
4136 //
4137 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4138 // domain is raising its power state, immediately after notifying interested
4139 // drivers and power children.
4140 //******************************************************************************
4141
4142 void
4143 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4144 {
4145 if ((_systemTransitionType == kSystemTransitionWake) &&
4146 !CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
4147 // After powering up drivers, dark->full promotion on the current wake
4148 // transition is no longer possible. That is because the next machine
4149 // state will issue the system capability change messages.
4150 // The darkWakePowerClamped flag may already be set if the system has
4151 // at least one driver that was power clamped due to dark wake.
4152 // This function sets the darkWakePowerClamped flag in case there
4153 // is no power-clamped driver in the system.
4154 //
4155 // Last opportunity to exit dark wake using:
4156 // requestFullWake( kFullWakeReasonLocalUser );
4157
4158 if (!darkWakePowerClamped) {
4159 if (darkWakeLogClamp) {
4160 AbsoluteTime now;
4161 uint64_t nsec;
4162
4163 clock_get_uptime(&now);
4164 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
4165 absolutetime_to_nanoseconds(now, &nsec);
4166 DLOG("dark wake promotion disabled at %u ms\n",
4167 ((int)((nsec) / NSEC_PER_MSEC)));
4168 }
4169 darkWakePowerClamped = true;
4170 }
4171 }
4172 }
4173
4174 //******************************************************************************
4175 // sleepOnClamshellClosed
4176 //
4177 // contains the logic to determine if the system should sleep when the clamshell
4178 // is closed.
4179 //******************************************************************************
4180
4181 bool
4182 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4183 {
4184 if (!clamshellExists) {
4185 return false;
4186 }
4187
4188 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4189 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4190
4191 return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4192 }
4193
4194 bool
4195 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4196 {
4197 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4198 // closed && battery
4199 if (!clamshellExists) {
4200 return false;
4201 }
4202
4203 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4204 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4205
4206 return !acAdaptorConnected && !clamshellSleepDisableMask;
4207 }
4208
4209 void
4210 IOPMrootDomain::sendClientClamshellNotification( void )
4211 {
4212 /* Only broadcast clamshell alert if clamshell exists. */
4213 if (!clamshellExists) {
4214 return;
4215 }
4216
4217 setProperty(kAppleClamshellStateKey,
4218 clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4219
4220 setProperty(kAppleClamshellCausesSleepKey,
4221 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4222
4223 /* Argument to message is a bitfiel of
4224 * ( kClamshellStateBit | kClamshellSleepBit )
4225 */
4226 messageClients(kIOPMMessageClamshellStateChange,
4227 (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4228 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4229 }
4230
4231 //******************************************************************************
4232 // getSleepSupported
4233 //
4234 // Deprecated
4235 //******************************************************************************
4236
4237 IOOptionBits
4238 IOPMrootDomain::getSleepSupported( void )
4239 {
4240 return platformSleepSupport;
4241 }
4242
4243 //******************************************************************************
4244 // setSleepSupported
4245 //
4246 // Deprecated
4247 //******************************************************************************
4248
4249 void
4250 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4251 {
4252 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4253 OSBitOrAtomic(flags, &platformSleepSupport);
4254 }
4255
4256 //******************************************************************************
4257 // setClamShellSleepDisable
4258 //
4259 //******************************************************************************
4260
4261 void
4262 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4263 {
4264 uint32_t oldMask;
4265
4266 // User client calls this in non-gated context
4267 if (gIOPMWorkLoop->inGate() == false) {
4268 gIOPMWorkLoop->runAction(
4269 OSMemberFunctionCast(IOWorkLoop::Action, this,
4270 &IOPMrootDomain::setClamShellSleepDisable),
4271 (OSObject *) this,
4272 (void *) disable, (void *)(uintptr_t) bitmask);
4273 return;
4274 }
4275
4276 oldMask = clamshellSleepDisableMask;
4277 if (disable) {
4278 clamshellSleepDisableMask |= bitmask;
4279 } else {
4280 clamshellSleepDisableMask &= ~bitmask;
4281 }
4282 DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4283
4284 if (clamshellExists && clamshellClosed &&
4285 (clamshellSleepDisableMask != oldMask) &&
4286 (clamshellSleepDisableMask == 0)) {
4287 handlePowerNotification(kLocalEvalClamshellCommand);
4288 }
4289 }
4290
4291 //******************************************************************************
4292 // wakeFromDoze
4293 //
4294 // Deprecated.
4295 //******************************************************************************
4296
4297 void
4298 IOPMrootDomain::wakeFromDoze( void )
4299 {
4300 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4301 }
4302
4303 //******************************************************************************
4304 // recordRTCAlarm
4305 //
4306 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4307 // should be a dark wake or a full wake. Both Maintenance and SleepService
4308 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4309 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4310 // PMSettings are ignored.
4311 //
4312 // Caller serialized using settingsCtrlLock.
4313 //******************************************************************************
4314
4315 void
4316 IOPMrootDomain::recordRTCAlarm(
4317 const OSSymbol *type,
4318 OSObject *object )
4319 {
4320 uint32_t previousAlarmMask = _scheduledAlarmMask;
4321
4322 if (type == gIOPMSettingDebugWakeRelativeKey) {
4323 OSNumber * n = OSDynamicCast(OSNumber, object);
4324 if (n) {
4325 // Debug wake has highest scheduling priority so it overrides any
4326 // pre-existing alarm.
4327 uint32_t debugSecs = n->unsigned32BitValue();
4328 _nextScheduledAlarmType.reset(type, OSRetain);
4329 _nextScheduledAlarmUTC = debugSecs;
4330
4331 _debugWakeSeconds = debugSecs;
4332 OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4333 DLOG("next alarm (%s) in %u secs\n",
4334 type->getCStringNoCopy(), debugSecs);
4335 }
4336 } else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) ||
4337 (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) ||
4338 (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) {
4339 OSData * data = OSDynamicCast(OSData, object);
4340 if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) {
4341 const IOPMCalendarStruct * cs;
4342 bool replaceNextAlarm = false;
4343 clock_sec_t secs;
4344
4345 cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4346 secs = IOPMConvertCalendarToSeconds(cs);
4347 DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4348
4349 // Update the next scheduled alarm type
4350 if ((_nextScheduledAlarmType == NULL) ||
4351 ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4352 (secs < _nextScheduledAlarmUTC))) {
4353 replaceNextAlarm = true;
4354 }
4355
4356 if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4357 if (cs->year) {
4358 _calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4359 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4360 } else {
4361 // TODO: can this else-block be removed?
4362 _calendarWakeAlarmUTC = 0;
4363 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4364 }
4365 }
4366 if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4367 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4368 }
4369 if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4370 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4371 }
4372
4373 if (replaceNextAlarm) {
4374 _nextScheduledAlarmType.reset(type, OSRetain);
4375 _nextScheduledAlarmUTC = secs;
4376 DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4377 }
4378 }
4379 }
4380
4381 if (_scheduledAlarmMask != previousAlarmMask) {
4382 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4383 }
4384 }
4385
4386 // MARK: -
4387 // MARK: Features
4388
4389 //******************************************************************************
4390 // publishFeature
4391 //
4392 // Adds a new feature to the supported features dictionary
4393 //******************************************************************************
4394
4395 void
4396 IOPMrootDomain::publishFeature( const char * feature )
4397 {
4398 publishFeature(feature, kRD_AllPowerSources, NULL);
4399 }
4400
4401 //******************************************************************************
4402 // publishFeature (with supported power source specified)
4403 //
4404 // Adds a new feature to the supported features dictionary
4405 //******************************************************************************
4406
4407 void
4408 IOPMrootDomain::publishFeature(
4409 const char *feature,
4410 uint32_t supportedWhere,
4411 uint32_t *uniqueFeatureID)
4412 {
4413 static uint16_t next_feature_id = 500;
4414
4415 OSSharedPtr<OSNumber> new_feature_data;
4416 OSNumber *existing_feature = NULL;
4417 OSArray *existing_feature_arr_raw = NULL;
4418 OSSharedPtr<OSArray> existing_feature_arr;
4419 OSObject *osObj = NULL;
4420 uint32_t feature_value = 0;
4421
4422 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4423
4424 if (!supportedWhere) {
4425 // Feature isn't supported anywhere!
4426 return;
4427 }
4428
4429 if (next_feature_id > 5000) {
4430 // Far, far too many features!
4431 return;
4432 }
4433
4434 if (featuresDictLock) {
4435 IOLockLock(featuresDictLock);
4436 }
4437
4438 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4439 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4440 OSSharedPtr<OSDictionary> features;
4441
4442 // Create new features dict if necessary
4443 if (origFeatures) {
4444 features = OSDictionary::withDictionary(origFeatures);
4445 } else {
4446 features = OSDictionary::withCapacity(1);
4447 }
4448
4449 // Create OSNumber to track new feature
4450
4451 next_feature_id += 1;
4452 if (uniqueFeatureID) {
4453 // We don't really mind if the calling kext didn't give us a place
4454 // to stash their unique id. Many kexts don't plan to unload, and thus
4455 // have no need to remove themselves later.
4456 *uniqueFeatureID = next_feature_id;
4457 }
4458
4459 feature_value = (uint32_t)next_feature_id;
4460 feature_value <<= 16;
4461 feature_value += supportedWhere;
4462
4463 new_feature_data = OSNumber::withNumber(
4464 (unsigned long long)feature_value, 32);
4465
4466 // Does features object already exist?
4467 if ((osObj = features->getObject(feature))) {
4468 if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
4469 // We need to create an OSArray to hold the now 2 elements.
4470 existing_feature_arr = OSArray::withObjects(
4471 (const OSObject **)&existing_feature, 1, 2);
4472 } else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) {
4473 // Add object to existing array
4474 existing_feature_arr = OSArray::withArray(
4475 existing_feature_arr_raw,
4476 existing_feature_arr_raw->getCount() + 1);
4477 }
4478
4479 if (existing_feature_arr) {
4480 existing_feature_arr->setObject(new_feature_data.get());
4481 features->setObject(feature, existing_feature_arr.get());
4482 }
4483 } else {
4484 // The easy case: no previously existing features listed. We simply
4485 // set the OSNumber at key 'feature' and we're on our way.
4486 features->setObject(feature, new_feature_data.get());
4487 }
4488
4489 setProperty(kRootDomainSupportedFeatures, features.get());
4490
4491 if (featuresDictLock) {
4492 IOLockUnlock(featuresDictLock);
4493 }
4494
4495 // Notify EnergySaver and all those in user space so they might
4496 // re-populate their feature specific UI
4497 if (pmPowerStateQueue) {
4498 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4499 }
4500 }
4501
4502 //******************************************************************************
4503 // removePublishedFeature
4504 //
4505 // Removes previously published feature
4506 //******************************************************************************
4507
4508 IOReturn
4509 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4510 {
4511 IOReturn ret = kIOReturnError;
4512 uint32_t feature_value = 0;
4513 uint16_t feature_id = 0;
4514 bool madeAChange = false;
4515
4516 OSSymbol *dictKey = NULL;
4517 OSSharedPtr<OSCollectionIterator> dictIterator;
4518 OSArray *arrayMember = NULL;
4519 OSNumber *numberMember = NULL;
4520 OSObject *osObj = NULL;
4521 OSNumber *osNum = NULL;
4522 OSSharedPtr<OSArray> arrayMemberCopy;
4523
4524 if (kBadPMFeatureID == removeFeatureID) {
4525 return kIOReturnNotFound;
4526 }
4527
4528 if (featuresDictLock) {
4529 IOLockLock(featuresDictLock);
4530 }
4531
4532 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4533 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4534 OSSharedPtr<OSDictionary> features;
4535
4536 if (origFeatures) {
4537 // Any modifications to the dictionary are made to the copy to prevent
4538 // races & crashes with userland clients. Dictionary updated
4539 // automically later.
4540 features = OSDictionary::withDictionary(origFeatures);
4541 } else {
4542 features = NULL;
4543 ret = kIOReturnNotFound;
4544 goto exit;
4545 }
4546
4547 // We iterate 'features' dictionary looking for an entry tagged
4548 // with 'removeFeatureID'. If found, we remove it from our tracking
4549 // structures and notify the OS via a general interest message.
4550
4551 dictIterator = OSCollectionIterator::withCollection(features.get());
4552 if (!dictIterator) {
4553 goto exit;
4554 }
4555
4556 while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4557 osObj = features->getObject(dictKey);
4558
4559 // Each Feature is either tracked by an OSNumber
4560 if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
4561 feature_value = numberMember->unsigned32BitValue();
4562 feature_id = (uint16_t)(feature_value >> 16);
4563
4564 if (feature_id == (uint16_t)removeFeatureID) {
4565 // Remove this node
4566 features->removeObject(dictKey);
4567 madeAChange = true;
4568 break;
4569 }
4570
4571 // Or tracked by an OSArray of OSNumbers
4572 } else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4573 unsigned int arrayCount = arrayMember->getCount();
4574
4575 for (unsigned int i = 0; i < arrayCount; i++) {
4576 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4577 if (!osNum) {
4578 continue;
4579 }
4580
4581 feature_value = osNum->unsigned32BitValue();
4582 feature_id = (uint16_t)(feature_value >> 16);
4583
4584 if (feature_id == (uint16_t)removeFeatureID) {
4585 // Remove this node
4586 if (1 == arrayCount) {
4587 // If the array only contains one element, remove
4588 // the whole thing.
4589 features->removeObject(dictKey);
4590 } else {
4591 // Otherwise remove the element from a copy of the array.
4592 arrayMemberCopy = OSArray::withArray(arrayMember);
4593 if (arrayMemberCopy) {
4594 arrayMemberCopy->removeObject(i);
4595 features->setObject(dictKey, arrayMemberCopy.get());
4596 }
4597 }
4598
4599 madeAChange = true;
4600 break;
4601 }
4602 }
4603 }
4604 }
4605
4606 if (madeAChange) {
4607 ret = kIOReturnSuccess;
4608
4609 setProperty(kRootDomainSupportedFeatures, features.get());
4610
4611 // Notify EnergySaver and all those in user space so they might
4612 // re-populate their feature specific UI
4613 if (pmPowerStateQueue) {
4614 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4615 }
4616 } else {
4617 ret = kIOReturnNotFound;
4618 }
4619
4620 exit:
4621 if (featuresDictLock) {
4622 IOLockUnlock(featuresDictLock);
4623 }
4624 return ret;
4625 }
4626
4627 //******************************************************************************
4628 // publishPMSetting (private)
4629 //
4630 // Should only be called by PMSettingObject to publish a PM Setting as a
4631 // supported feature.
4632 //******************************************************************************
4633
4634 void
4635 IOPMrootDomain::publishPMSetting(
4636 const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4637 {
4638 if (noPublishPMSettings &&
4639 (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4640 // Setting found in noPublishPMSettings array
4641 *featureID = kBadPMFeatureID;
4642 return;
4643 }
4644
4645 publishFeature(
4646 feature->getCStringNoCopy(), where, featureID);
4647 }
4648
4649 //******************************************************************************
4650 // setPMSetting (private)
4651 //
4652 // Internal helper to relay PM settings changes from user space to individual
4653 // drivers. Should be called only by IOPMrootDomain::setProperties.
4654 //******************************************************************************
4655
4656 IOReturn
4657 IOPMrootDomain::setPMSetting(
4658 const OSSymbol *type,
4659 OSObject *object )
4660 {
4661 PMSettingCallEntry *entries = NULL;
4662 OSSharedPtr<OSArray> chosen;
4663 const OSArray *array;
4664 PMSettingObject *pmso;
4665 thread_t thisThread;
4666 int i, j, count, capacity;
4667 bool ok = false;
4668 IOReturn ret;
4669
4670 if (NULL == type) {
4671 return kIOReturnBadArgument;
4672 }
4673
4674 PMSETTING_LOCK();
4675
4676 // Update settings dict so changes are visible from copyPMSetting().
4677 fPMSettingsDict->setObject(type, object);
4678
4679 // Prep all PMSetting objects with the given 'type' for callout.
4680 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
4681 if (!array || ((capacity = array->getCount()) == 0)) {
4682 goto unlock_exit;
4683 }
4684
4685 // Array to retain PMSetting objects targeted for callout.
4686 chosen = OSArray::withCapacity(capacity);
4687 if (!chosen) {
4688 goto unlock_exit; // error
4689 }
4690 entries = IONew(PMSettingCallEntry, capacity);
4691 if (!entries) {
4692 goto unlock_exit; // error
4693 }
4694 memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4695
4696 thisThread = current_thread();
4697
4698 for (i = 0, j = 0; i < capacity; i++) {
4699 pmso = (PMSettingObject *) array->getObject(i);
4700 if (pmso->disabled) {
4701 continue;
4702 }
4703 entries[j].thread = thisThread;
4704 queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4705 chosen->setObject(pmso);
4706 j++;
4707 }
4708 count = j;
4709 if (!count) {
4710 goto unlock_exit;
4711 }
4712
4713 PMSETTING_UNLOCK();
4714
4715 // Call each pmso in the chosen array.
4716 for (i = 0; i < count; i++) {
4717 pmso = (PMSettingObject *) chosen->getObject(i);
4718 ret = pmso->dispatchPMSetting(type, object);
4719 if (ret == kIOReturnSuccess) {
4720 // At least one setting handler was successful
4721 ok = true;
4722 #if DEVELOPMENT || DEBUG
4723 } else {
4724 // Log the handler and kext that failed
4725 OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
4726 if (kextName) {
4727 DLOG("PMSetting(%s) error 0x%x from %s\n",
4728 type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
4729 }
4730 #endif
4731 }
4732 }
4733
4734 PMSETTING_LOCK();
4735 for (i = 0; i < count; i++) {
4736 pmso = (PMSettingObject *) chosen->getObject(i);
4737 queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
4738 if (pmso->waitThread) {
4739 PMSETTING_WAKEUP(pmso);
4740 }
4741 }
4742
4743 if (ok) {
4744 recordRTCAlarm(type, object);
4745 }
4746 unlock_exit:
4747 PMSETTING_UNLOCK();
4748
4749 if (entries) {
4750 IODelete(entries, PMSettingCallEntry, capacity);
4751 }
4752
4753 return kIOReturnSuccess;
4754 }
4755
4756 //******************************************************************************
4757 // copyPMSetting (public)
4758 //
4759 // Allows kexts to safely read setting values, without being subscribed to
4760 // notifications.
4761 //******************************************************************************
4762
4763 OSSharedPtr<OSObject>
4764 IOPMrootDomain::copyPMSetting(
4765 OSSymbol *whichSetting)
4766 {
4767 OSSharedPtr<OSObject> obj;
4768
4769 if (!whichSetting) {
4770 return NULL;
4771 }
4772
4773 PMSETTING_LOCK();
4774 obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
4775 PMSETTING_UNLOCK();
4776
4777 return obj;
4778 }
4779
4780 //******************************************************************************
4781 // registerPMSettingController (public)
4782 //
4783 // direct wrapper to registerPMSettingController with uint32_t power source arg
4784 //******************************************************************************
4785
4786 IOReturn
4787 IOPMrootDomain::registerPMSettingController(
4788 const OSSymbol * settings[],
4789 IOPMSettingControllerCallback func,
4790 OSObject *target,
4791 uintptr_t refcon,
4792 OSObject **handle)
4793 {
4794 return registerPMSettingController(
4795 settings,
4796 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
4797 func, target, refcon, handle);
4798 }
4799
4800 //******************************************************************************
4801 // registerPMSettingController (public)
4802 //
4803 // Kexts may register for notifications when a particular setting is changed.
4804 // A list of settings is available in IOPM.h.
4805 // Arguments:
4806 // * settings - An OSArray containing OSSymbols. Caller should populate this
4807 // array with a list of settings caller wants notifications from.
4808 // * func - A C function callback of the type IOPMSettingControllerCallback
4809 // * target - caller may provide an OSObject *, which PM will pass as an
4810 // target to calls to "func"
4811 // * refcon - caller may provide an void *, which PM will pass as an
4812 // argument to calls to "func"
4813 // * handle - This is a return argument. We will populate this pointer upon
4814 // call success. Hold onto this and pass this argument to
4815 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4816 // Returns:
4817 // kIOReturnSuccess on success
4818 //******************************************************************************
4819
4820 IOReturn
4821 IOPMrootDomain::registerPMSettingController(
4822 const OSSymbol * settings[],
4823 uint32_t supportedPowerSources,
4824 IOPMSettingControllerCallback func,
4825 OSObject *target,
4826 uintptr_t refcon,
4827 OSObject **handle)
4828 {
4829 PMSettingObject *pmso = NULL;
4830 OSObject *pmsh = NULL;
4831 int i;
4832
4833 if (NULL == settings ||
4834 NULL == func ||
4835 NULL == handle) {
4836 return kIOReturnBadArgument;
4837 }
4838
4839 pmso = PMSettingObject::pmSettingObject(
4840 (IOPMrootDomain *) this, func, target,
4841 refcon, supportedPowerSources, settings, &pmsh);
4842
4843 if (!pmso) {
4844 *handle = NULL;
4845 return kIOReturnInternalError;
4846 }
4847
4848 PMSETTING_LOCK();
4849 for (i = 0; settings[i]; i++) {
4850 OSSharedPtr<OSArray> newList;
4851 OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
4852 if (!list) {
4853 // New array of callbacks for this setting
4854 newList = OSArray::withCapacity(1);
4855 settingsCallbacks->setObject(settings[i], newList.get());
4856 list = newList.get();
4857 }
4858
4859 // Add caller to the callback list
4860 list->setObject(pmso);
4861 }
4862 PMSETTING_UNLOCK();
4863
4864 // Return handle to the caller, the setting object is private.
4865 *handle = pmsh;
4866
4867 return kIOReturnSuccess;
4868 }
4869
4870 //******************************************************************************
4871 // deregisterPMSettingObject (private)
4872 //
4873 // Only called from PMSettingObject.
4874 //******************************************************************************
4875
4876 void
4877 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
4878 {
4879 thread_t thisThread = current_thread();
4880 PMSettingCallEntry *callEntry;
4881 OSSharedPtr<OSCollectionIterator> iter;
4882 OSSymbol *sym;
4883 OSArray *array;
4884 int index;
4885 bool wait;
4886
4887 PMSETTING_LOCK();
4888
4889 pmso->disabled = true;
4890
4891 // Wait for all callout threads to finish.
4892 do {
4893 wait = false;
4894 queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
4895 {
4896 if (callEntry->thread != thisThread) {
4897 wait = true;
4898 break;
4899 }
4900 }
4901 if (wait) {
4902 assert(NULL == pmso->waitThread);
4903 pmso->waitThread = thisThread;
4904 PMSETTING_WAIT(pmso);
4905 pmso->waitThread = NULL;
4906 }
4907 } while (wait);
4908
4909 // Search each PM settings array in the kernel.
4910 iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
4911 if (iter) {
4912 while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
4913 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
4914 index = array->getNextIndexOfObject(pmso, 0);
4915 if (-1 != index) {
4916 array->removeObject(index);
4917 }
4918 }
4919 }
4920
4921 PMSETTING_UNLOCK();
4922
4923 pmso->release();
4924 }
4925
4926 //******************************************************************************
4927 // informCPUStateChange
4928 //
4929 // Call into PM CPU code so that CPU power savings may dynamically adjust for
4930 // running on battery, with the lid closed, etc.
4931 //
4932 // informCPUStateChange is a no-op on non x86 systems
4933 // only x86 has explicit support in the IntelCPUPowerManagement kext
4934 //******************************************************************************
4935
4936 void
4937 IOPMrootDomain::informCPUStateChange(
4938 uint32_t type,
4939 uint32_t value )
4940 {
4941 #if defined(__i386__) || defined(__x86_64__)
4942
4943 pmioctlVariableInfo_t varInfoStruct;
4944 int pmCPUret = 0;
4945 const char *varNameStr = NULL;
4946 int32_t *varIndex = NULL;
4947
4948 if (kInformAC == type) {
4949 varNameStr = kIOPMRootDomainBatPowerCString;
4950 varIndex = &idxPMCPULimitedPower;
4951 } else if (kInformLid == type) {
4952 varNameStr = kIOPMRootDomainLidCloseCString;
4953 varIndex = &idxPMCPUClamshell;
4954 } else {
4955 return;
4956 }
4957
4958 // Set the new value!
4959 // pmCPUControl will assign us a new ID if one doesn't exist yet
4960 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
4961 varInfoStruct.varID = *varIndex;
4962 varInfoStruct.varType = vBool;
4963 varInfoStruct.varInitValue = value;
4964 varInfoStruct.varCurValue = value;
4965 strlcpy((char *)varInfoStruct.varName,
4966 (const char *)varNameStr,
4967 sizeof(varInfoStruct.varName));
4968
4969 // Set!
4970 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
4971
4972 // pmCPU only assigns numerical id's when a new varName is specified
4973 if ((0 == pmCPUret)
4974 && (*varIndex == kCPUUnknownIndex)) {
4975 // pmCPUControl has assigned us a new variable ID.
4976 // Let's re-read the structure we just SET to learn that ID.
4977 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
4978
4979 if (0 == pmCPUret) {
4980 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
4981 *varIndex = varInfoStruct.varID;
4982 }
4983 }
4984
4985 return;
4986
4987 #endif /* __i386__ || __x86_64__ */
4988 }
4989
4990 // MARK: -
4991 // MARK: Deep Sleep Policy
4992
4993 #if HIBERNATION
4994
4995 //******************************************************************************
4996 // evaluateSystemSleepPolicy
4997 //******************************************************************************
4998
4999 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
5000
5001 // Sleep flags
5002 enum {
5003 kIOPMSleepFlagHibernate = 0x00000001,
5004 kIOPMSleepFlagSleepTimerEnable = 0x00000002
5005 };
5006
5007 struct IOPMSystemSleepPolicyEntry {
5008 uint32_t factorMask;
5009 uint32_t factorBits;
5010 uint32_t sleepFlags;
5011 uint32_t wakeEvents;
5012 } __attribute__((packed));
5013
5014 struct IOPMSystemSleepPolicyTable {
5015 uint32_t signature;
5016 uint16_t version;
5017 uint16_t entryCount;
5018 IOPMSystemSleepPolicyEntry entries[];
5019 } __attribute__((packed));
5020
5021 enum {
5022 kIOPMSleepAttributeHibernateSetup = 0x00000001,
5023 kIOPMSleepAttributeHibernateSleep = 0x00000002
5024 };
5025
5026 static uint32_t
5027 getSleepTypeAttributes( uint32_t sleepType )
5028 {
5029 static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5030 {
5031 /* invalid */ 0,
5032 /* abort */ 0,
5033 /* normal */ 0,
5034 /* safesleep */ kIOPMSleepAttributeHibernateSetup,
5035 /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5036 /* standby */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5037 /* poweroff */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5038 /* deepidle */ 0
5039 };
5040
5041 if (sleepType >= kIOPMSleepTypeLast) {
5042 return 0;
5043 }
5044
5045 return sleepTypeAttributes[sleepType];
5046 }
5047
5048 bool
5049 IOPMrootDomain::evaluateSystemSleepPolicy(
5050 IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5051 {
5052 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5053
5054 static const IONamedValue factorValues[] = {
5055 SLEEP_FACTOR( SleepTimerWake ),
5056 SLEEP_FACTOR( LidOpen ),
5057 SLEEP_FACTOR( ACPower ),
5058 SLEEP_FACTOR( BatteryLow ),
5059 SLEEP_FACTOR( StandbyNoDelay ),
5060 SLEEP_FACTOR( StandbyForced ),
5061 SLEEP_FACTOR( StandbyDisabled ),
5062 SLEEP_FACTOR( USBExternalDevice ),
5063 SLEEP_FACTOR( BluetoothHIDDevice ),
5064 SLEEP_FACTOR( ExternalMediaMounted ),
5065 SLEEP_FACTOR( ThunderboltDevice ),
5066 SLEEP_FACTOR( RTCAlarmScheduled ),
5067 SLEEP_FACTOR( MagicPacketWakeEnabled ),
5068 SLEEP_FACTOR( HibernateForced ),
5069 SLEEP_FACTOR( AutoPowerOffDisabled ),
5070 SLEEP_FACTOR( AutoPowerOffForced ),
5071 SLEEP_FACTOR( ExternalDisplay ),
5072 SLEEP_FACTOR( NetworkKeepAliveActive ),
5073 SLEEP_FACTOR( LocalUserActivity ),
5074 SLEEP_FACTOR( HibernateFailed ),
5075 SLEEP_FACTOR( ThermalWarning ),
5076 SLEEP_FACTOR( DisplayCaptured ),
5077 { 0, NULL }
5078 };
5079
5080 const IOPMSystemSleepPolicyTable * pt;
5081 OSSharedPtr<OSObject> prop;
5082 OSData * policyData;
5083 uint64_t currentFactors = 0;
5084 char currentFactorsBuf[512];
5085 uint32_t standbyDelay = 0;
5086 uint32_t powerOffDelay = 0;
5087 uint32_t powerOffTimer = 0;
5088 uint32_t standbyTimer = 0;
5089 uint32_t mismatch;
5090 bool standbyEnabled;
5091 bool powerOffEnabled;
5092 bool found = false;
5093
5094 // Get platform's sleep policy table
5095 if (!gSleepPolicyHandler) {
5096 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5097 if (!prop) {
5098 goto done;
5099 }
5100 }
5101
5102 // Fetch additional settings
5103 standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
5104 && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue));
5105 powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
5106 && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue));
5107 if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
5108 powerOffTimer = powerOffDelay;
5109 }
5110 if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5111 standbyTimer = standbyDelay;
5112 }
5113
5114 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5115 sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
5116 powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
5117
5118 currentFactorsBuf[0] = 0;
5119 // pmset level overrides
5120 if ((*hibMode & kIOHibernateModeOn) == 0) {
5121 if (!gSleepPolicyHandler) {
5122 standbyEnabled = false;
5123 powerOffEnabled = false;
5124 }
5125 } else if (!(*hibMode & kIOHibernateModeSleep)) {
5126 // Force hibernate (i.e. mode 25)
5127 // If standby is enabled, force standy.
5128 // If poweroff is enabled, force poweroff.
5129 if (standbyEnabled) {
5130 currentFactors |= kIOPMSleepFactorStandbyForced;
5131 } else if (powerOffEnabled) {
5132 currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
5133 } else {
5134 currentFactors |= kIOPMSleepFactorHibernateForced;
5135 }
5136 }
5137
5138 // Current factors based on environment and assertions
5139 if (sleepTimerMaintenance) {
5140 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5141 }
5142 if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5143 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5144 }
5145 if (!clamshellClosed) {
5146 currentFactors |= kIOPMSleepFactorLidOpen;
5147 }
5148 if (acAdaptorConnected) {
5149 currentFactors |= kIOPMSleepFactorACPower;
5150 }
5151 if (lowBatteryCondition) {
5152 hibernateMode = 0;
5153 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5154 if ((hibernateMode & kIOHibernateModeOn) == 0) {
5155 DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5156 } else {
5157 currentFactors |= kIOPMSleepFactorBatteryLow;
5158 }
5159 }
5160 if (!standbyDelay || !standbyTimer) {
5161 currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5162 }
5163 if (standbyNixed || !standbyEnabled) {
5164 currentFactors |= kIOPMSleepFactorStandbyDisabled;
5165 }
5166 if (resetTimers) {
5167 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5168 currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5169 }
5170 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5171 kIOPMDriverAssertionLevelOff) {
5172 currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5173 }
5174 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5175 kIOPMDriverAssertionLevelOff) {
5176 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5177 }
5178 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5179 kIOPMDriverAssertionLevelOff) {
5180 currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5181 }
5182 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5183 kIOPMDriverAssertionLevelOff) {
5184 currentFactors |= kIOPMSleepFactorThunderboltDevice;
5185 }
5186 if (_scheduledAlarmMask != 0) {
5187 currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5188 }
5189 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5190 kIOPMDriverAssertionLevelOff) {
5191 currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5192 }
5193 #define TCPKEEPALIVE 1
5194 #if TCPKEEPALIVE
5195 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5196 kIOPMDriverAssertionLevelOff) {
5197 currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5198 }
5199 #endif
5200 if (!powerOffEnabled) {
5201 currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5202 }
5203 if (desktopMode) {
5204 currentFactors |= kIOPMSleepFactorExternalDisplay;
5205 }
5206 if (userWasActive) {
5207 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5208 }
5209 if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5210 currentFactors |= kIOPMSleepFactorHibernateFailed;
5211 }
5212 if (thermalWarningState) {
5213 currentFactors |= kIOPMSleepFactorThermalWarning;
5214 }
5215
5216 for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) {
5217 uint32_t factor = 1 << factorBit;
5218 if (factor & currentFactors) {
5219 strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf));
5220 strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf));
5221 }
5222 }
5223 DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5224
5225 if (gSleepPolicyHandler) {
5226 uint32_t savedHibernateMode;
5227 IOReturn result;
5228
5229 if (!gSleepPolicyVars) {
5230 gSleepPolicyVars = IONew(IOPMSystemSleepPolicyVariables, 1);
5231 if (!gSleepPolicyVars) {
5232 goto done;
5233 }
5234 bzero(gSleepPolicyVars, sizeof(*gSleepPolicyVars));
5235 }
5236 gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
5237 gSleepPolicyVars->version = kIOPMSystemSleepPolicyVersion;
5238 gSleepPolicyVars->currentCapability = _currentCapability;
5239 gSleepPolicyVars->highestCapability = _highestCapability;
5240 gSleepPolicyVars->sleepFactors = currentFactors;
5241 gSleepPolicyVars->sleepReason = lastSleepReason;
5242 gSleepPolicyVars->sleepPhase = sleepPhase;
5243 gSleepPolicyVars->standbyDelay = standbyDelay;
5244 gSleepPolicyVars->standbyTimer = standbyTimer;
5245 gSleepPolicyVars->poweroffDelay = powerOffDelay;
5246 gSleepPolicyVars->scheduledAlarms = _scheduledAlarmMask | _userScheduledAlarmMask;
5247 gSleepPolicyVars->poweroffTimer = powerOffTimer;
5248
5249 if (kIOPMSleepPhase0 == sleepPhase) {
5250 // preserve hibernateMode
5251 savedHibernateMode = gSleepPolicyVars->hibernateMode;
5252 gSleepPolicyVars->hibernateMode = *hibMode;
5253 } else if (kIOPMSleepPhase1 == sleepPhase) {
5254 // use original hibernateMode for phase2
5255 gSleepPolicyVars->hibernateMode = *hibMode;
5256 }
5257
5258 result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5259
5260 if (kIOPMSleepPhase0 == sleepPhase) {
5261 // restore hibernateMode
5262 gSleepPolicyVars->hibernateMode = savedHibernateMode;
5263 }
5264
5265 if ((result != kIOReturnSuccess) ||
5266 (kIOPMSleepTypeInvalid == params->sleepType) ||
5267 (params->sleepType >= kIOPMSleepTypeLast) ||
5268 (kIOPMSystemSleepParametersVersion != params->version)) {
5269 MSG("sleep policy handler error\n");
5270 goto done;
5271 }
5272
5273 if ((getSleepTypeAttributes(params->sleepType) &
5274 kIOPMSleepAttributeHibernateSetup) &&
5275 ((*hibMode & kIOHibernateModeOn) == 0)) {
5276 *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5277 }
5278
5279 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5280 params->version, params->sleepType, params->sleepFlags,
5281 params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
5282 found = true;
5283 goto done;
5284 }
5285
5286 // Policy table is meaningless without standby enabled
5287 if (!standbyEnabled) {
5288 goto done;
5289 }
5290
5291 // Validate the sleep policy table
5292 policyData = OSDynamicCast(OSData, prop.get());
5293 if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5294 goto done;
5295 }
5296
5297 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5298 if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5299 (pt->version != 1) || (0 == pt->entryCount)) {
5300 goto done;
5301 }
5302
5303 if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5304 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5305 goto done;
5306 }
5307
5308 for (uint32_t i = 0; i < pt->entryCount; i++) {
5309 const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
5310 mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
5311
5312 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5313 entry->factorMask, entry->factorBits,
5314 entry->sleepFlags, entry->wakeEvents, mismatch);
5315 if (mismatch) {
5316 continue;
5317 }
5318
5319 DLOG("^ found match\n");
5320 found = true;
5321
5322 params->version = kIOPMSystemSleepParametersVersion;
5323 params->reserved1 = 1;
5324 if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5325 params->sleepType = kIOPMSleepTypeStandby;
5326 } else {
5327 params->sleepType = kIOPMSleepTypeNormalSleep;
5328 }
5329
5330 params->ecWakeEvents = entry->wakeEvents;
5331 if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5332 if (kIOPMSleepPhase2 == sleepPhase) {
5333 clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5334
5335 if (!_standbyTimerResetSeconds ||
5336 (now_secs <= _standbyTimerResetSeconds)) {
5337 // Reset standby timer adjustment
5338 _standbyTimerResetSeconds = now_secs;
5339 DLOG("standby delay %u, reset %u\n",
5340 standbyDelay, (uint32_t) _standbyTimerResetSeconds);
5341 } else if (standbyDelay) {
5342 // Shorten the standby delay timer
5343 clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
5344 if (standbyDelay > elapsed) {
5345 standbyDelay -= elapsed;
5346 } else {
5347 standbyDelay = 1; // must be > 0
5348 }
5349 DLOG("standby delay %u, elapsed %u\n",
5350 standbyDelay, (uint32_t) elapsed);
5351 }
5352 }
5353 params->ecWakeTimer = standbyDelay;
5354 } else if (kIOPMSleepPhase2 == sleepPhase) {
5355 // A sleep that does not enable the sleep timer will reset
5356 // the standby delay adjustment.
5357 _standbyTimerResetSeconds = 0;
5358 }
5359 break;
5360 }
5361
5362 done:
5363 return found;
5364 }
5365
5366 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5367
5368 void
5369 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5370 {
5371 // Evaluate early (priority interest phase), before drivers sleep.
5372
5373 DLOG("%s\n", __FUNCTION__);
5374 removeProperty(kIOPMSystemSleepParametersKey);
5375
5376 // Full wake resets the standby timer delay adjustment
5377 if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5378 _standbyTimerResetSeconds = 0;
5379 }
5380
5381 hibernateDisabled = false;
5382 hibernateMode = 0;
5383 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5384
5385 // Save for late evaluation if sleep is aborted
5386 bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5387
5388 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5389 &hibernateMode)) {
5390 if (!hibernateRetry &&
5391 ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5392 kIOPMSleepAttributeHibernateSetup) == 0)) {
5393 // skip hibernate setup
5394 hibernateDisabled = true;
5395 }
5396 }
5397
5398 // Publish IOPMSystemSleepType
5399 uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5400 if (sleepType == kIOPMSleepTypeInvalid) {
5401 // no sleep policy
5402 sleepType = kIOPMSleepTypeNormalSleep;
5403 if (hibernateMode & kIOHibernateModeOn) {
5404 sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5405 kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5406 }
5407 } else if ((sleepType == kIOPMSleepTypeStandby) &&
5408 (gEarlySystemSleepParams.ecPoweroffTimer)) {
5409 // report the lowest possible sleep state
5410 sleepType = kIOPMSleepTypePowerOff;
5411 }
5412
5413 setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5414 }
5415
5416 void
5417 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5418 {
5419 IOPMSystemSleepParameters params;
5420 OSSharedPtr<OSData> paramsData;
5421 bool wakeNow;
5422 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5423
5424 DLOG("%s\n", __FUNCTION__);
5425
5426 bzero(&params, sizeof(params));
5427 wakeNow = false;
5428 if (evaluateSystemSleepPolicy(&params, kIOPMSleepPhase2, &hibernateMode)) {
5429 if ((kIOPMSleepTypeStandby == params.sleepType)
5430 && gIOHibernateStandbyDisabled && gSleepPolicyVars
5431 && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5432 & gSleepPolicyVars->sleepFactors))) {
5433 standbyNixed = true;
5434 wakeNow = true;
5435 }
5436 if (wakeNow
5437 || ((hibernateDisabled || hibernateAborted) &&
5438 (getSleepTypeAttributes(params.sleepType) &
5439 kIOPMSleepAttributeHibernateSetup))) {
5440 // Final evaluation picked a state requiring hibernation,
5441 // but hibernate isn't going to proceed. Arm a short sleep using
5442 // the early non-hibernate sleep parameters.
5443 bcopy(&gEarlySystemSleepParams, &params, sizeof(params));
5444 params.sleepType = kIOPMSleepTypeAbortedSleep;
5445 params.ecWakeTimer = 1;
5446 if (standbyNixed) {
5447 resetTimers = true;
5448 } else {
5449 // Set hibernateRetry flag to force hibernate setup on the
5450 // next sleep.
5451 hibernateRetry = true;
5452 }
5453 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5454 params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5455 } else {
5456 hibernateRetry = false;
5457 }
5458
5459 if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5460 resetTimers = false;
5461 }
5462
5463 paramsData = OSData::withBytes(&params, sizeof(params));
5464 if (paramsData) {
5465 setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5466 }
5467
5468 if (getSleepTypeAttributes(params.sleepType) &
5469 kIOPMSleepAttributeHibernateSleep) {
5470 // Disable sleep to force hibernation
5471 gIOHibernateMode &= ~kIOHibernateModeSleep;
5472 }
5473 }
5474 }
5475
5476 bool
5477 IOPMrootDomain::getHibernateSettings(
5478 uint32_t * hibernateModePtr,
5479 uint32_t * hibernateFreeRatio,
5480 uint32_t * hibernateFreeTime )
5481 {
5482 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5483 // has updated the hibernateDisabled flag.
5484
5485 bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
5486 getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
5487 getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
5488 if (hibernateDisabled) {
5489 *hibernateModePtr = 0;
5490 } else if (gSleepPolicyHandler) {
5491 *hibernateModePtr = hibernateMode;
5492 }
5493 DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5494 return ok;
5495 }
5496
5497 bool
5498 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5499 {
5500 OSSharedPtr<OSObject> optionsProp;
5501 OSDictionary * optionsDict;
5502 OSSharedPtr<OSObject> obj;
5503 OSNumber * num;
5504 bool ok = false;
5505
5506 optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5507 optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5508
5509 if (optionsDict) {
5510 obj.reset(optionsDict->getObject(key), OSRetain);
5511 }
5512 if (!obj) {
5513 obj = copyProperty(key);
5514 }
5515 if (obj) {
5516 if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5517 *option = num->unsigned32BitValue();
5518 ok = true;
5519 } else if (OSDynamicCast(OSBoolean, obj.get())) {
5520 *option = (obj == kOSBooleanTrue) ? 1 : 0;
5521 ok = true;
5522 }
5523 }
5524
5525 return ok;
5526 }
5527 #endif /* HIBERNATION */
5528
5529 IOReturn
5530 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5531 {
5532 #if HIBERNATION
5533 IOPMSystemSleepParameters params;
5534 uint32_t hibMode = 0;
5535 bool ok;
5536
5537 if (gIOPMWorkLoop->inGate() == false) {
5538 IOReturn ret = gIOPMWorkLoop->runAction(
5539 OSMemberFunctionCast(IOWorkLoop::Action, this,
5540 &IOPMrootDomain::getSystemSleepType),
5541 (OSObject *) this,
5542 (void *) sleepType, (void *) standbyTimer);
5543 return ret;
5544 }
5545
5546 getSleepOption(kIOHibernateModeKey, &hibMode);
5547 bzero(&params, sizeof(params));
5548
5549 ok = evaluateSystemSleepPolicy(&params, kIOPMSleepPhase0, &hibMode);
5550 if (ok) {
5551 *sleepType = params.sleepType;
5552 if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5553 !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5554 DLOG("Standby delay is not set\n");
5555 *standbyTimer = 0;
5556 }
5557 return kIOReturnSuccess;
5558 }
5559 #endif
5560
5561 return kIOReturnUnsupported;
5562 }
5563
5564 // MARK: -
5565 // MARK: Shutdown and Restart
5566
5567 //******************************************************************************
5568 // handlePlatformHaltRestart
5569 //
5570 //******************************************************************************
5571
5572 // Phases while performing shutdown/restart
5573 typedef enum {
5574 kNotifyDone = 0x00,
5575 kNotifyPriorityClients = 0x10,
5576 kNotifyPowerPlaneDrivers = 0x20,
5577 kNotifyHaltRestartAction = 0x30,
5578 kQuiescePM = 0x40,
5579 } shutdownPhase_t;
5580
5581
5582 struct HaltRestartApplierContext {
5583 IOPMrootDomain * RootDomain;
5584 unsigned long PowerState;
5585 IOPMPowerFlags PowerFlags;
5586 UInt32 MessageType;
5587 UInt32 Counter;
5588 const char * LogString;
5589 shutdownPhase_t phase;
5590
5591 IOServiceInterestHandler handler;
5592 } gHaltRestartCtx;
5593
5594 const char *
5595 shutdownPhase2String(shutdownPhase_t phase)
5596 {
5597 switch (phase) {
5598 case kNotifyDone:
5599 return "Notifications completed";
5600 case kNotifyPriorityClients:
5601 return "Notifying priority clients";
5602 case kNotifyPowerPlaneDrivers:
5603 return "Notifying power plane drivers";
5604 case kNotifyHaltRestartAction:
5605 return "Notifying HaltRestart action handlers";
5606 case kQuiescePM:
5607 return "Quiescing PM";
5608 default:
5609 return "Unknown";
5610 }
5611 }
5612
5613 static void
5614 platformHaltRestartApplier( OSObject * object, void * context )
5615 {
5616 IOPowerStateChangeNotification notify;
5617 HaltRestartApplierContext * ctx;
5618 AbsoluteTime startTime, elapsedTime;
5619 uint32_t deltaTime;
5620
5621 ctx = (HaltRestartApplierContext *) context;
5622
5623 _IOServiceInterestNotifier * notifier;
5624 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5625 memset(&notify, 0, sizeof(notify));
5626 notify.powerRef = (void *)(uintptr_t)ctx->Counter;
5627 notify.returnValue = 0;
5628 notify.stateNumber = ctx->PowerState;
5629 notify.stateFlags = ctx->PowerFlags;
5630
5631 if (notifier) {
5632 ctx->handler = notifier->handler;
5633 }
5634
5635 clock_get_uptime(&startTime);
5636 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
5637 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5638
5639 if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
5640 LOG("%s handler %p took %u ms\n",
5641 ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
5642 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
5643 }
5644
5645 ctx->handler = NULL;
5646 ctx->Counter++;
5647 }
5648
5649 static void
5650 quiescePowerTreeCallback( void * target, void * param )
5651 {
5652 IOLockLock(gPMHaltLock);
5653 gPMQuiesced = true;
5654 thread_wakeup(param);
5655 IOLockUnlock(gPMHaltLock);
5656 }
5657
5658 void
5659 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5660 {
5661 AbsoluteTime startTime, elapsedTime;
5662 uint32_t deltaTime;
5663
5664 memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5665 gHaltRestartCtx.RootDomain = this;
5666
5667 clock_get_uptime(&startTime);
5668 switch (pe_type) {
5669 case kPEHaltCPU:
5670 case kPEUPSDelayHaltCPU:
5671 gHaltRestartCtx.PowerState = OFF_STATE;
5672 gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5673 gHaltRestartCtx.LogString = "PowerOff";
5674 break;
5675
5676 case kPERestartCPU:
5677 gHaltRestartCtx.PowerState = RESTART_STATE;
5678 gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5679 gHaltRestartCtx.LogString = "Restart";
5680 break;
5681
5682 case kPEPagingOff:
5683 gHaltRestartCtx.PowerState = ON_STATE;
5684 gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5685 gHaltRestartCtx.LogString = "PagingOff";
5686 IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5687 #if HIBERNATION
5688 IOHibernateSystemRestart();
5689 #endif
5690 break;
5691
5692 default:
5693 return;
5694 }
5695
5696 gHaltRestartCtx.phase = kNotifyPriorityClients;
5697 // Notify legacy clients
5698 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5699
5700 // For normal shutdown, turn off File Server Mode.
5701 if (kPEHaltCPU == pe_type) {
5702 OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
5703 OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32);
5704 if (setting && num) {
5705 setPMSetting(setting.get(), num.get());
5706 }
5707 }
5708
5709 if (kPEPagingOff != pe_type) {
5710 gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5711 // Notify in power tree order
5712 notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5713 }
5714
5715 gHaltRestartCtx.phase = kNotifyHaltRestartAction;
5716 #if defined(XNU_TARGET_OS_OSX)
5717 IOCPURunPlatformHaltRestartActions(pe_type);
5718 #else /* !defined(XNU_TARGET_OS_OSX) */
5719 if (kPEPagingOff != pe_type) {
5720 IOCPURunPlatformHaltRestartActions(pe_type);
5721 }
5722 #endif /* !defined(XNU_TARGET_OS_OSX) */
5723
5724 // Wait for PM to quiesce
5725 if ((kPEPagingOff != pe_type) && gPMHaltLock) {
5726 gHaltRestartCtx.phase = kQuiescePM;
5727 AbsoluteTime quiesceTime = mach_absolute_time();
5728
5729 IOLockLock(gPMHaltLock);
5730 gPMQuiesced = false;
5731 if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
5732 kIOReturnSuccess) {
5733 while (!gPMQuiesced) {
5734 IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
5735 }
5736 }
5737 IOLockUnlock(gPMHaltLock);
5738 deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
5739 DLOG("PM quiesce took %u ms\n", deltaTime);
5740 halt_log_enter("Quiesce", NULL, elapsedTime);
5741 }
5742 gHaltRestartCtx.phase = kNotifyDone;
5743
5744 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5745 LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5746
5747 halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
5748
5749 deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5750 LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5751
5752 if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
5753 printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
5754 }
5755
5756 checkShutdownTimeout();
5757 }
5758
5759 bool
5760 IOPMrootDomain::checkShutdownTimeout()
5761 {
5762 AbsoluteTime elapsedTime;
5763 uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5764
5765 if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
5766 return true;
5767 }
5768 return false;
5769 }
5770
5771 void
5772 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
5773 {
5774 if (gHaltLog) {
5775 if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
5776 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
5777 }
5778 panic("%s timed out in phase '%s'. Total %d ms:%s",
5779 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
5780 } else {
5781 panic("%s timed out in phase \'%s\'. Total %d ms",
5782 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
5783 }
5784 }
5785
5786 //******************************************************************************
5787 // shutdownSystem
5788 //
5789 //******************************************************************************
5790
5791 IOReturn
5792 IOPMrootDomain::shutdownSystem( void )
5793 {
5794 return kIOReturnUnsupported;
5795 }
5796
5797 //******************************************************************************
5798 // restartSystem
5799 //
5800 //******************************************************************************
5801
5802 IOReturn
5803 IOPMrootDomain::restartSystem( void )
5804 {
5805 return kIOReturnUnsupported;
5806 }
5807
5808 // MARK: -
5809 // MARK: System Capability
5810
5811 //******************************************************************************
5812 // tagPowerPlaneService
5813 //
5814 // Running on PM work loop thread.
5815 //******************************************************************************
5816
5817 void
5818 IOPMrootDomain::tagPowerPlaneService(
5819 IOService * service,
5820 IOPMActions * actions,
5821 IOPMPowerStateIndex maxPowerState )
5822 {
5823 uint32_t flags = 0;
5824
5825 memset(actions, 0, sizeof(*actions));
5826 actions->target = this;
5827
5828 if (service == this) {
5829 actions->actionPowerChangeStart =
5830 OSMemberFunctionCast(
5831 IOPMActionPowerChangeStart, this,
5832 &IOPMrootDomain::handleOurPowerChangeStart);
5833
5834 actions->actionPowerChangeDone =
5835 OSMemberFunctionCast(
5836 IOPMActionPowerChangeDone, this,
5837 &IOPMrootDomain::handleOurPowerChangeDone);
5838
5839 actions->actionPowerChangeOverride =
5840 OSMemberFunctionCast(
5841 IOPMActionPowerChangeOverride, this,
5842 &IOPMrootDomain::overrideOurPowerChange);
5843 return;
5844 }
5845
5846 #if DISPLAY_WRANGLER_PRESENT
5847 if (NULL != service->metaCast("IODisplayWrangler")) {
5848 // XXX should this really retain?
5849 wrangler.reset(service, OSRetain);
5850 wrangler->registerInterest(gIOGeneralInterest,
5851 &displayWranglerNotification, this, NULL);
5852
5853 // found the display wrangler, check for any display assertions already created
5854 if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
5855 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5856 wrangler->setIgnoreIdleTimer( true );
5857 }
5858 flags |= kPMActionsFlagIsDisplayWrangler;
5859 }
5860 #endif /* DISPLAY_WRANGLER_PRESENT */
5861
5862 if (service->propertyExists("IOPMStrictTreeOrder")) {
5863 flags |= kPMActionsFlagIsGraphicsDriver;
5864 }
5865 if (service->propertyExists("IOPMUnattendedWakePowerState")) {
5866 flags |= kPMActionsFlagIsAudioDriver;
5867 }
5868
5869 OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
5870 if (prop) {
5871 OSNumber * num = OSDynamicCast(OSNumber, prop.get());
5872 if (num) {
5873 actions->darkWakePowerState = num->unsigned32BitValue();
5874 if (actions->darkWakePowerState < maxPowerState) {
5875 flags |= kPMActionsFlagHasDarkWakePowerState;
5876 }
5877 }
5878 }
5879
5880 // Find the power connection object that is a child of the PCI host
5881 // bridge, and has a graphics/audio device attached below. Mark the
5882 // power branch for delayed child notifications.
5883
5884 if (flags) {
5885 IORegistryEntry * child = service;
5886 IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
5887
5888 while (child != this) {
5889 if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) {
5890 // Skip delaying notifications and clamping power on external graphics and audio devices.
5891 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
5892 flags = 0;
5893 break;
5894 }
5895 if ((parent == pciHostBridgeDriver) ||
5896 (parent == this)) {
5897 if (OSDynamicCast(IOPowerConnection, child)) {
5898 IOPowerConnection * conn = (IOPowerConnection *) child;
5899 conn->delayChildNotification = true;
5900 DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
5901 }
5902 break;
5903 }
5904 child = parent;
5905 parent = child->getParentEntry(gIOPowerPlane);
5906 }
5907 }
5908
5909 if (flags) {
5910 DLOG("%s tag flags %x\n", service->getName(), flags);
5911 actions->flags |= flags;
5912 actions->actionPowerChangeOverride =
5913 OSMemberFunctionCast(
5914 IOPMActionPowerChangeOverride, this,
5915 &IOPMrootDomain::overridePowerChangeForService);
5916
5917 if (flags & kPMActionsFlagIsDisplayWrangler) {
5918 actions->actionActivityTickle =
5919 OSMemberFunctionCast(
5920 IOPMActionActivityTickle, this,
5921 &IOPMrootDomain::handleActivityTickleForDisplayWrangler);
5922
5923 actions->actionUpdatePowerClient =
5924 OSMemberFunctionCast(
5925 IOPMActionUpdatePowerClient, this,
5926 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
5927 }
5928 return;
5929 }
5930
5931 // Locate the first PCI host bridge for PMTrace.
5932 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
5933 IOService * provider = service->getProvider();
5934 if (OSDynamicCast(IOPlatformDevice, provider) &&
5935 provider->inPlane(gIODTPlane)) {
5936 pciHostBridgeDevice.reset(provider, OSNoRetain);
5937 pciHostBridgeDriver.reset(service, OSNoRetain);
5938 DLOG("PMTrace found PCI host bridge %s->%s\n",
5939 provider->getName(), service->getName());
5940 }
5941 }
5942
5943 // Tag top-level PCI devices. The order of PMinit() call does not
5944 // change across boots and is used as the PCI bit number.
5945 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
5946 // Would prefer to check built-in property, but tagPowerPlaneService()
5947 // is called before pciDevice->registerService().
5948 IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
5949 if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) {
5950 int bit = pmTracer->recordTopLevelPCIDevice( service );
5951 if (bit >= 0) {
5952 // Save the assigned bit for fast lookup.
5953 actions->flags |= (bit & kPMActionsPCIBitNumberMask);
5954
5955 actions->actionPowerChangeStart =
5956 OSMemberFunctionCast(
5957 IOPMActionPowerChangeStart, this,
5958 &IOPMrootDomain::handlePowerChangeStartForPCIDevice);
5959
5960 actions->actionPowerChangeDone =
5961 OSMemberFunctionCast(
5962 IOPMActionPowerChangeDone, this,
5963 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
5964 }
5965 }
5966 }
5967 }
5968
5969 //******************************************************************************
5970 // PM actions for root domain
5971 //******************************************************************************
5972
5973 void
5974 IOPMrootDomain::overrideOurPowerChange(
5975 IOService * service,
5976 IOPMActions * actions,
5977 const IOPMRequest * request,
5978 IOPMPowerStateIndex * inOutPowerState,
5979 IOPMPowerChangeFlags * inOutChangeFlags )
5980 {
5981 uint32_t changeFlags = *inOutChangeFlags;
5982 uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
5983 uint32_t currentPowerState = (uint32_t) getPowerState();
5984
5985 if (request->getTag() == 0) {
5986 // Set a tag for any request that originates from IOServicePM
5987 (const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
5988 }
5989
5990 DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
5991 getPowerStateString(currentPowerState),
5992 getPowerStateString(desiredPowerState),
5993 _currentCapability, changeFlags,
5994 request->getTag());
5995
5996 if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
5997 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
5998 *inOutChangeFlags |= kIOPMNotDone;
5999 return;
6000 }
6001
6002 if (changeFlags & kIOPMParentInitiated) {
6003 // Root parent is permanently pegged at max power,
6004 // a parent initiated power change is unexpected.
6005 *inOutChangeFlags |= kIOPMNotDone;
6006 return;
6007 }
6008
6009 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6010 if (lowBatteryCondition && (desiredPowerState < currentPowerState)) {
6011 // Reject sleep requests when lowBatteryCondition is TRUE to
6012 // avoid racing with the impending system shutdown.
6013 *inOutChangeFlags |= kIOPMNotDone;
6014 return;
6015 }
6016 #endif
6017
6018 if (desiredPowerState < currentPowerState) {
6019 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6020 // Root domain is dropping power state from ON->SLEEP.
6021 // If system is in full wake, first enter dark wake by
6022 // converting the power drop to a capability change.
6023 // Once in dark wake, transition to sleep state ASAP.
6024
6025 darkWakeToSleepASAP = true;
6026
6027 // Drop graphics and audio capability
6028 _desiredCapability &= ~(
6029 kIOPMSystemCapabilityGraphics |
6030 kIOPMSystemCapabilityAudio);
6031
6032 // Convert to capability change (ON->ON)
6033 *inOutPowerState = getRUN_STATE();
6034 *inOutChangeFlags |= kIOPMSynchronize;
6035
6036 // Revert device desire from SLEEP to ON
6037 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6038 } else {
6039 // System is already in dark wake, ok to drop power state.
6040 // Broadcast root power down to entire tree.
6041 *inOutChangeFlags |= kIOPMRootChangeDown;
6042 }
6043 } else if (desiredPowerState > currentPowerState) {
6044 if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
6045 // Broadcast power up when waking from sleep, but not for the
6046 // initial power change at boot by checking for cpu capability.
6047 *inOutChangeFlags |= kIOPMRootChangeUp;
6048 }
6049 }
6050 }
6051
6052 void
6053 IOPMrootDomain::handleOurPowerChangeStart(
6054 IOService * service,
6055 IOPMActions * actions,
6056 const IOPMRequest * request,
6057 IOPMPowerStateIndex newPowerState,
6058 IOPMPowerChangeFlags * inOutChangeFlags )
6059 {
6060 IOPMRequestTag requestTag = request->getTag();
6061 IOPMRequestTag sleepReason;
6062
6063 uint32_t changeFlags = *inOutChangeFlags;
6064 uint32_t currentPowerState = (uint32_t) getPowerState();
6065 bool publishSleepReason = false;
6066
6067 // Check if request has a valid sleep reason
6068 sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6069 if (sleepReason < kIOPMSleepReasonClamshell) {
6070 sleepReason = kIOPMSleepReasonIdle;
6071 }
6072
6073 _systemTransitionType = kSystemTransitionNone;
6074 _systemMessageClientMask = 0;
6075 capabilityLoss = false;
6076 toldPowerdCapWillChange = false;
6077
6078 // Emergency notifications may arrive after the initial sleep request
6079 // has been queued. Override the sleep reason so powerd and others can
6080 // treat this as an emergency sleep.
6081 if (lowBatteryCondition) {
6082 sleepReason = kIOPMSleepReasonLowPower;
6083 } else if (thermalEmergencyState) {
6084 sleepReason = kIOPMSleepReasonThermalEmergency;
6085 }
6086
6087 // 1. Explicit capability change.
6088 if (changeFlags & kIOPMSynchronize) {
6089 if (newPowerState == ON_STATE) {
6090 if (changeFlags & kIOPMSyncNoChildNotify) {
6091 _systemTransitionType = kSystemTransitionNewCapClient;
6092 } else {
6093 _systemTransitionType = kSystemTransitionCapability;
6094 }
6095 }
6096 }
6097 // 2. Going to sleep (cancellation still possible).
6098 else if (newPowerState < currentPowerState) {
6099 _systemTransitionType = kSystemTransitionSleep;
6100 }
6101 // 3. Woke from (idle or demand) sleep.
6102 else if (!systemBooting &&
6103 (changeFlags & kIOPMSelfInitiated) &&
6104 (newPowerState > currentPowerState)) {
6105 _systemTransitionType = kSystemTransitionWake;
6106 _desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
6107
6108 // Early exit from dark wake to full (e.g. LID open)
6109 if (kFullWakeReasonNone != fullWakeReason) {
6110 _desiredCapability |= (
6111 kIOPMSystemCapabilityGraphics |
6112 kIOPMSystemCapabilityAudio);
6113
6114 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6115 if (fullWakeReason == kFullWakeReasonLocalUser) {
6116 darkWakeExit = true;
6117 darkWakeToSleepASAP = false;
6118 setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ?
6119 kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser);
6120 }
6121 #endif
6122 }
6123 #if HIBERNATION
6124 IOHibernateSetWakeCapabilities(_desiredCapability);
6125 #endif
6126 }
6127
6128 // Update pending wake capability at the beginning of every
6129 // state transition (including synchronize). This will become
6130 // the current capability at the end of the transition.
6131
6132 if (kSystemTransitionSleep == _systemTransitionType) {
6133 _pendingCapability = 0;
6134 capabilityLoss = true;
6135 } else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6136 _pendingCapability = _desiredCapability |
6137 kIOPMSystemCapabilityCPU |
6138 kIOPMSystemCapabilityNetwork;
6139
6140 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6141 _pendingCapability |= kIOPMSystemCapabilityAudio;
6142 }
6143
6144 if ((kSystemTransitionCapability == _systemTransitionType) &&
6145 (_pendingCapability == _currentCapability)) {
6146 // Cancel the PM state change.
6147 _systemTransitionType = kSystemTransitionNone;
6148 *inOutChangeFlags |= kIOPMNotDone;
6149 }
6150 if (__builtin_popcount(_pendingCapability) <
6151 __builtin_popcount(_currentCapability)) {
6152 capabilityLoss = true;
6153 }
6154 }
6155
6156 // 1. Capability change.
6157 if (kSystemTransitionCapability == _systemTransitionType) {
6158 // Dark to Full transition.
6159 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6160 tracePoint( kIOPMTracePointDarkWakeExit );
6161
6162 #if defined(XNU_TARGET_OS_OSX)
6163 // rdar://problem/65627936
6164 // When a dark->full wake promotion is scheduled before an ON->SLEEP
6165 // power state drop, invalidate any request to drop power state already
6166 // in the queue, including the override variant, unless full wake cannot
6167 // be sustained. Any power state drop queued after this SustainFullWake
6168 // request will not be affected.
6169 if (checkSystemCanSustainFullWake()) {
6170 changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake);
6171 }
6172 #endif
6173
6174 willEnterFullWake();
6175 }
6176
6177 // Full to Dark transition.
6178 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6179 // Clear previous stats
6180 IOLockLock(pmStatsLock);
6181 if (pmStatsAppResponses) {
6182 pmStatsAppResponses = OSArray::withCapacity(5);
6183 }
6184 IOLockUnlock(pmStatsLock);
6185
6186 tracePoint( kIOPMTracePointDarkWakeEntry );
6187 *inOutChangeFlags |= kIOPMSyncTellPowerDown;
6188 _systemMessageClientMask = kSystemMessageClientPowerd |
6189 kSystemMessageClientLegacyApp;
6190
6191 // rdar://15971327
6192 // Prevent user active transitions before notifying clients
6193 // that system will sleep.
6194 preventTransitionToUserActive(true);
6195
6196 IOService::setAdvisoryTickleEnable( false );
6197
6198 // Publish the sleep reason for full to dark wake
6199 publishSleepReason = true;
6200 lastSleepReason = fullToDarkReason = sleepReason;
6201
6202 // Publish a UUID for the Sleep --> Wake cycle
6203 handlePublishSleepWakeUUID(true);
6204 if (sleepDelaysReport) {
6205 clock_get_uptime(&ts_sleepStart);
6206 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
6207 }
6208
6209 darkWakeExit = false;
6210 }
6211 }
6212 // 2. System sleep.
6213 else if (kSystemTransitionSleep == _systemTransitionType) {
6214 // Beginning of a system sleep transition.
6215 // Cancellation is still possible.
6216 tracePoint( kIOPMTracePointSleepStarted );
6217
6218 _systemMessageClientMask = kSystemMessageClientAll;
6219 if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6220 _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6221 }
6222 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
6223 // Kernel priority clients are only notified on the initial
6224 // transition to full wake, so don't notify them unless system
6225 // has gained graphics capability since the last system wake.
6226 _systemMessageClientMask &= ~kSystemMessageClientKernel;
6227 } else {
6228 // System was in full wake, but the downwards power transition is driven
6229 // by a request that originates from IOServicePM, so it isn't tagged with
6230 // a valid system sleep reason.
6231 if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) {
6232 // Publish the same reason for full to dark
6233 sleepReason = fullToDarkReason;
6234 }
6235 }
6236 #if HIBERNATION
6237 gIOHibernateState = 0;
6238 #endif
6239
6240 // Record the reason for dark wake back to sleep
6241 // System may not have ever achieved full wake
6242
6243 publishSleepReason = true;
6244 lastSleepReason = sleepReason;
6245 if (sleepDelaysReport) {
6246 clock_get_uptime(&ts_sleepStart);
6247 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
6248 }
6249 }
6250 // 3. System wake.
6251 else if (kSystemTransitionWake == _systemTransitionType) {
6252 tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6253 // Clear stats about sleep
6254
6255 if (AOT_STATE == newPowerState) {
6256 _pendingCapability = 0;
6257 }
6258
6259 if (AOT_STATE == currentPowerState) {
6260 // Wake events are no longer accepted after waking to AOT_STATE.
6261 // Re-enable wake event acceptance to append wake events claimed
6262 // during the AOT to ON_STATE transition.
6263 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable);
6264 }
6265
6266 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6267 willEnterFullWake();
6268 }
6269 }
6270
6271 // The only location where the sleep reason is published. At this point
6272 // sleep can still be cancelled, but sleep reason should be published
6273 // early for logging purposes.
6274
6275 if (publishSleepReason) {
6276 static const char * IOPMSleepReasons[] =
6277 {
6278 kIOPMClamshellSleepKey,
6279 kIOPMPowerButtonSleepKey,
6280 kIOPMSoftwareSleepKey,
6281 kIOPMOSSwitchHibernationKey,
6282 kIOPMIdleSleepKey,
6283 kIOPMLowPowerSleepKey,
6284 kIOPMThermalEmergencySleepKey,
6285 kIOPMMaintenanceSleepKey,
6286 kIOPMSleepServiceExitKey,
6287 kIOPMDarkWakeThermalEmergencyKey,
6288 kIOPMNotificationWakeExitKey
6289 };
6290
6291 // Record sleep cause in IORegistry
6292 uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
6293 if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
6294 DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
6295 setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
6296 }
6297 }
6298
6299 if ((kSystemTransitionNone != _systemTransitionType) &&
6300 (kSystemTransitionNewCapClient != _systemTransitionType)) {
6301 _systemStateGeneration++;
6302 systemDarkWake = false;
6303
6304 DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6305 getPowerStateString(currentPowerState),
6306 getPowerStateString((uint32_t) newPowerState),
6307 _currentCapability, _pendingCapability,
6308 *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask,
6309 requestTag);
6310 }
6311
6312 if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6313 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6314 }
6315 if (_aotNow && (ON_STATE == newPowerState)) {
6316 WAKEEVENT_LOCK();
6317 aotShouldExit(false, true);
6318 WAKEEVENT_UNLOCK();
6319 aotExit(false);
6320 }
6321 }
6322
6323 void
6324 IOPMrootDomain::handleOurPowerChangeDone(
6325 IOService * service,
6326 IOPMActions * actions,
6327 const IOPMRequest * request,
6328 IOPMPowerStateIndex oldPowerState,
6329 IOPMPowerChangeFlags changeFlags )
6330 {
6331 if (kSystemTransitionNewCapClient == _systemTransitionType) {
6332 _systemTransitionType = kSystemTransitionNone;
6333 return;
6334 }
6335
6336 if (_systemTransitionType != kSystemTransitionNone) {
6337 uint32_t currentPowerState = (uint32_t) getPowerState();
6338
6339 if (changeFlags & kIOPMNotDone) {
6340 // Power down was cancelled or vetoed.
6341 _pendingCapability = _currentCapability;
6342 lastSleepReason = 0;
6343
6344 // When sleep is cancelled or reverted, don't report
6345 // the target (lower) power state as the previous state.
6346 oldPowerState = currentPowerState;
6347
6348 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
6349 CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
6350 #if defined(XNU_TARGET_OS_OSX)
6351 pmPowerStateQueue->submitPowerEvent(
6352 kPowerEventPolicyStimulus,
6353 (void *) kStimulusDarkWakeReentry,
6354 _systemStateGeneration );
6355 #else /* !defined(XNU_TARGET_OS_OSX) */
6356 // On embedded, there are no factors that can prolong a
6357 // "darkWake" when a power down is vetoed. We need to
6358 // promote to "fullWake" at least once so that factors
6359 // that prevent idle sleep can assert themselves if required
6360 pmPowerStateQueue->submitPowerEvent(
6361 kPowerEventPolicyStimulus,
6362 (void *) kStimulusDarkWakeActivityTickle);
6363 #endif /* !defined(XNU_TARGET_OS_OSX) */
6364 }
6365
6366 // Revert device desire to max.
6367 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6368 } else {
6369 // Send message on dark wake to full wake promotion.
6370 // tellChangeUp() handles the normal SLEEP->ON case.
6371
6372 if (kSystemTransitionCapability == _systemTransitionType) {
6373 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6374 lastSleepReason = 0; // stop logging wrangler tickles
6375 tellClients(kIOMessageSystemHasPoweredOn);
6376 }
6377 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6378 // Going dark, reset full wake state
6379 // userIsActive will be cleared by wrangler powering down
6380 fullWakeReason = kFullWakeReasonNone;
6381
6382 if (ts_sleepStart) {
6383 clock_get_uptime(&wake2DarkwakeDelay);
6384 SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
6385 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
6386 ts_sleepStart = 0;
6387 }
6388 }
6389 }
6390
6391 // Reset state after exiting from dark wake.
6392
6393 if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6394 CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6395 darkWakeMaintenance = false;
6396 darkWakeToSleepASAP = false;
6397 pciCantSleepValid = false;
6398 darkWakeSleepService = false;
6399
6400 if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6401 // Remove the influence of display power assertion
6402 // before next system wake.
6403 if (wrangler) {
6404 wrangler->changePowerStateForRootDomain(
6405 kWranglerPowerStateMin );
6406 }
6407 removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6408 }
6409 }
6410
6411 // Entered dark mode.
6412
6413 if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6414 (_pendingCapability & kIOPMSystemCapabilityCPU)) {
6415 // Queue an evaluation of whether to remain in dark wake,
6416 // and for how long. This serves the purpose of draining
6417 // any assertions from the queue.
6418
6419 pmPowerStateQueue->submitPowerEvent(
6420 kPowerEventPolicyStimulus,
6421 (void *) kStimulusDarkWakeEntry,
6422 _systemStateGeneration );
6423 }
6424 }
6425
6426 DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6427 getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState),
6428 _currentCapability, _pendingCapability,
6429 changeFlags, _systemStateGeneration, _systemMessageClientMask,
6430 request->getTag());
6431
6432 if ((currentPowerState == ON_STATE) && pmAssertions) {
6433 pmAssertions->reportCPUBitAccounting();
6434 }
6435
6436 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6437 displayWakeCnt++;
6438 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6439 if (clamshellExists && fullWakeThreadCall) {
6440 AbsoluteTime deadline;
6441 clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline);
6442 thread_call_enter_delayed(fullWakeThreadCall, deadline);
6443 }
6444 #endif
6445 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6446 darkWakeCnt++;
6447 }
6448
6449 // Update current system capability.
6450 if (_currentCapability != _pendingCapability) {
6451 _currentCapability = _pendingCapability;
6452 }
6453
6454 // Update highest system capability.
6455
6456 _highestCapability |= _currentCapability;
6457
6458 if (darkWakePostTickle &&
6459 (kSystemTransitionWake == _systemTransitionType) &&
6460 (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6461 kDarkWakeFlagPromotionLate) {
6462 darkWakePostTickle = false;
6463 reportUserInput();
6464 } else if (darkWakeExit) {
6465 requestFullWake( kFullWakeReasonLocalUser );
6466 }
6467
6468 // Reset tracepoint at completion of capability change,
6469 // completion of wake transition, and aborted sleep transition.
6470
6471 if ((_systemTransitionType == kSystemTransitionCapability) ||
6472 (_systemTransitionType == kSystemTransitionWake) ||
6473 ((_systemTransitionType == kSystemTransitionSleep) &&
6474 (changeFlags & kIOPMNotDone))) {
6475 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6476 tracePoint( kIOPMTracePointSystemUp );
6477 }
6478
6479 _systemTransitionType = kSystemTransitionNone;
6480 _systemMessageClientMask = 0;
6481 toldPowerdCapWillChange = false;
6482
6483 darkWakeLogClamp = false;
6484
6485 if (lowBatteryCondition) {
6486 privateSleepSystem(kIOPMSleepReasonLowPower);
6487 } else if (thermalEmergencyState) {
6488 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6489 } else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) {
6490 // Request for full wake is removed while system is waking up to full wake
6491 DLOG("DisplayOn fullwake request is removed\n");
6492 handleSetDisplayPowerOn(false);
6493 }
6494
6495 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6496 pmPowerStateQueue->submitPowerEvent(
6497 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6498 }
6499 }
6500 }
6501
6502 //******************************************************************************
6503 // PM actions for graphics and audio.
6504 //******************************************************************************
6505
6506 void
6507 IOPMrootDomain::overridePowerChangeForService(
6508 IOService * service,
6509 IOPMActions * actions,
6510 const IOPMRequest * request,
6511 IOPMPowerStateIndex * inOutPowerState,
6512 IOPMPowerChangeFlags * inOutChangeFlags )
6513 {
6514 uint32_t powerState = (uint32_t) *inOutPowerState;
6515 uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6516 const uint32_t actionFlags = actions->flags;
6517
6518 if (kSystemTransitionNone == _systemTransitionType) {
6519 // Not in midst of a system transition.
6520 // Do not set kPMActionsStatePowerClamped.
6521 } else if ((actions->state & kPMActionsStatePowerClamped) == 0) {
6522 bool enableClamp = false;
6523
6524 // For most drivers, enable the clamp during ON->Dark transition
6525 // which has the kIOPMSynchronize flag set in changeFlags.
6526 if ((actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6527 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6528 (changeFlags & kIOPMSynchronize)) {
6529 enableClamp = true;
6530 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6531 ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6532 ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6533 (changeFlags & kIOPMSynchronize)) {
6534 enableClamp = true;
6535 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6536 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6537 (changeFlags & kIOPMSynchronize)) {
6538 enableClamp = true;
6539 } else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) &&
6540 (_systemTransitionType == kSystemTransitionSleep)) {
6541 // For graphics drivers, clamp power when entering
6542 // system sleep. Not when dropping to dark wake.
6543 enableClamp = true;
6544 }
6545
6546 if (enableClamp) {
6547 actions->state |= kPMActionsStatePowerClamped;
6548 DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6549 service->getName(), service->getRegistryEntryID(),
6550 _pendingCapability, powerState, changeFlags);
6551 }
6552 } else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6553 bool disableClamp = false;
6554
6555 if ((actionFlags & (
6556 kPMActionsFlagIsDisplayWrangler |
6557 kPMActionsFlagIsGraphicsDriver)) &&
6558 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6559 disableClamp = true;
6560 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6561 (_pendingCapability & kIOPMSystemCapabilityAudio)) {
6562 disableClamp = true;
6563 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6564 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6565 disableClamp = true;
6566 }
6567
6568 if (disableClamp) {
6569 actions->state &= ~kPMActionsStatePowerClamped;
6570 DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6571 service->getName(), service->getRegistryEntryID(),
6572 _pendingCapability, powerState, changeFlags);
6573 }
6574 }
6575
6576 if (actions->state & kPMActionsStatePowerClamped) {
6577 uint32_t maxPowerState = 0;
6578
6579 // Determine the max power state allowed when clamp is enabled
6580 if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
6581 // Parent intiated power state changes
6582 if ((service->getPowerState() > maxPowerState) &&
6583 (actionFlags & kPMActionsFlagIsDisplayWrangler)) {
6584 maxPowerState++;
6585
6586 // Remove lingering effects of any tickle before entering
6587 // dark wake. It will take a new tickle to return to full
6588 // wake, so the existing tickle state is useless.
6589
6590 if (changeFlags & kIOPMDomainDidChange) {
6591 *inOutChangeFlags |= kIOPMExpireIdleTimer;
6592 }
6593 } else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6594 maxPowerState++;
6595 } else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6596 maxPowerState = actions->darkWakePowerState;
6597 }
6598 } else {
6599 // Deny all self-initiated changes when power is limited.
6600 // Wrangler tickle should never defeat the limiter.
6601 maxPowerState = service->getPowerState();
6602 }
6603
6604 if (powerState > maxPowerState) {
6605 DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6606 service->getName(), service->getRegistryEntryID(),
6607 powerState, maxPowerState, changeFlags);
6608 *inOutPowerState = maxPowerState;
6609
6610 if (darkWakePostTickle &&
6611 (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6612 (changeFlags & kIOPMDomainWillChange) &&
6613 ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6614 kDarkWakeFlagPromotionEarly)) {
6615 darkWakePostTickle = false;
6616 reportUserInput();
6617 }
6618 }
6619
6620 if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
6621 if (darkWakeLogClamp) {
6622 AbsoluteTime now;
6623 uint64_t nsec;
6624
6625 clock_get_uptime(&now);
6626 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
6627 absolutetime_to_nanoseconds(now, &nsec);
6628 DLOG("dark wake power clamped after %u ms\n",
6629 ((int)((nsec) / NSEC_PER_MSEC)));
6630 }
6631 darkWakePowerClamped = true;
6632 }
6633 }
6634 }
6635
6636 void
6637 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6638 IOService * service,
6639 IOPMActions * actions )
6640 {
6641 #if DISPLAY_WRANGLER_PRESENT
6642 // Warning: Not running in PM work loop context - don't modify state !!!
6643 // Trap tickle directed to IODisplayWrangler while running with graphics
6644 // capability suppressed.
6645
6646 assert(service == wrangler);
6647
6648 clock_get_uptime(&userActivityTime);
6649 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
6650 || (lastSleepReason == kIOPMSleepReasonMaintenance)
6651 || (lastSleepReason == kIOPMSleepReasonSoftware));
6652 if (aborting) {
6653 userActivityCount++;
6654 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6655 userActivityCount, lastSleepReason);
6656 }
6657
6658 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
6659 DLOG("display wrangler tickled\n");
6660 if (kIOLogPMRootDomain & gIOKitDebug) {
6661 OSReportWithBacktrace("Dark wake display tickle");
6662 }
6663 if (pmPowerStateQueue) {
6664 pmPowerStateQueue->submitPowerEvent(
6665 kPowerEventPolicyStimulus,
6666 (void *) kStimulusDarkWakeActivityTickle,
6667 true /* set wake type */ );
6668 }
6669 }
6670 #endif /* DISPLAY_WRANGLER_PRESENT */
6671 }
6672
6673 void
6674 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6675 IOService * service,
6676 IOPMActions * actions,
6677 const OSSymbol * powerClient,
6678 IOPMPowerStateIndex oldPowerState,
6679 IOPMPowerStateIndex newPowerState )
6680 {
6681 #if DISPLAY_WRANGLER_PRESENT
6682 assert(service == wrangler);
6683
6684 // This function implements half of the user active detection
6685 // by monitoring changes to the display wrangler's device desire.
6686 //
6687 // User becomes active when either:
6688 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6689 // in max power state. This desire change in absence of a power state
6690 // change is detected within. This handles the case when user becomes
6691 // active while the display is already lit by setDisplayPowerOn().
6692 //
6693 // 2. Power state change to max, and DeviceDesire is also at max.
6694 // Handled by displayWranglerNotification().
6695 //
6696 // User becomes inactive when DeviceDesire drops to sleep state or below.
6697
6698 DLOG("wrangler %s (ps %u, %u->%u)\n",
6699 powerClient->getCStringNoCopy(),
6700 (uint32_t) service->getPowerState(),
6701 (uint32_t) oldPowerState, (uint32_t) newPowerState);
6702
6703 if (powerClient == gIOPMPowerClientDevice) {
6704 if ((newPowerState > oldPowerState) &&
6705 (newPowerState == kWranglerPowerStateMax) &&
6706 (service->getPowerState() == kWranglerPowerStateMax)) {
6707 evaluatePolicy( kStimulusEnterUserActiveState );
6708 } else if ((newPowerState < oldPowerState) &&
6709 (newPowerState <= kWranglerPowerStateSleep)) {
6710 evaluatePolicy( kStimulusLeaveUserActiveState );
6711 }
6712 }
6713
6714 if (newPowerState <= kWranglerPowerStateSleep) {
6715 evaluatePolicy( kStimulusDisplayWranglerSleep );
6716 } else if (newPowerState == kWranglerPowerStateMax) {
6717 evaluatePolicy( kStimulusDisplayWranglerWake );
6718 }
6719 #endif /* DISPLAY_WRANGLER_PRESENT */
6720 }
6721
6722 //******************************************************************************
6723 // User active state management
6724 //******************************************************************************
6725
6726 void
6727 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
6728 {
6729 #if DISPLAY_WRANGLER_PRESENT
6730 _preventUserActive = prevent;
6731 if (wrangler && !_preventUserActive) {
6732 // Allowing transition to user active, but the wrangler may have
6733 // already powered ON in case of sleep cancel/revert. Poll the
6734 // same conditions checked for in displayWranglerNotification()
6735 // to bring the user active state up to date.
6736
6737 if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
6738 (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
6739 kWranglerPowerStateMax)) {
6740 evaluatePolicy( kStimulusEnterUserActiveState );
6741 }
6742 }
6743 #endif /* DISPLAY_WRANGLER_PRESENT */
6744 }
6745
6746 //******************************************************************************
6747 // Approve usage of delayed child notification by PM.
6748 //******************************************************************************
6749
6750 bool
6751 IOPMrootDomain::shouldDelayChildNotification(
6752 IOService * service )
6753 {
6754 if ((kFullWakeReasonNone == fullWakeReason) &&
6755 (kSystemTransitionWake == _systemTransitionType)) {
6756 DLOG("%s: delay child notify\n", service->getName());
6757 return true;
6758 }
6759 return false;
6760 }
6761
6762 //******************************************************************************
6763 // PM actions for PCI device.
6764 //******************************************************************************
6765
6766 void
6767 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6768 IOService * service,
6769 IOPMActions * actions,
6770 const IOPMRequest * request,
6771 IOPMPowerStateIndex powerState,
6772 IOPMPowerChangeFlags * inOutChangeFlags )
6773 {
6774 pmTracer->tracePCIPowerChange(
6775 PMTraceWorker::kPowerChangeStart,
6776 service, *inOutChangeFlags,
6777 (actions->flags & kPMActionsPCIBitNumberMask));
6778 }
6779
6780 void
6781 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6782 IOService * service,
6783 IOPMActions * actions,
6784 const IOPMRequest * request,
6785 IOPMPowerStateIndex powerState,
6786 IOPMPowerChangeFlags changeFlags )
6787 {
6788 pmTracer->tracePCIPowerChange(
6789 PMTraceWorker::kPowerChangeCompleted,
6790 service, changeFlags,
6791 (actions->flags & kPMActionsPCIBitNumberMask));
6792 }
6793
6794 //******************************************************************************
6795 // registerInterest
6796 //
6797 // Override IOService::registerInterest() for root domain clients.
6798 //******************************************************************************
6799
6800 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
6801 {
6802 friend class IOPMrootDomain;
6803 OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
6804
6805 protected:
6806 uint32_t ackTimeoutCnt;
6807 uint32_t msgType; // Message pending ack
6808 uint32_t msgIndex;
6809 uint32_t maxMsgDelayMS;
6810 uint32_t maxAckDelayMS;
6811 uint64_t msgAbsTime;
6812 uint64_t uuid0;
6813 uint64_t uuid1;
6814 OSSharedPtr<const OSSymbol> identifier;
6815 OSSharedPtr<const OSSymbol> clientName;
6816 };
6817
6818 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
6819
6820 OSSharedPtr<IONotifier>
6821 IOPMrootDomain::registerInterest(
6822 const OSSymbol * typeOfInterest,
6823 IOServiceInterestHandler handler,
6824 void * target, void * ref )
6825 {
6826 IOPMServiceInterestNotifier* notifier;
6827 bool isSystemCapabilityClient;
6828 bool isKernelCapabilityClient;
6829 IOReturn rc = kIOReturnError;
6830
6831 isSystemCapabilityClient = typeOfInterest &&
6832 typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
6833
6834 isKernelCapabilityClient = typeOfInterest &&
6835 typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
6836
6837 if (isSystemCapabilityClient) {
6838 typeOfInterest = gIOAppPowerStateInterest;
6839 }
6840
6841 notifier = new IOPMServiceInterestNotifier;
6842 if (!notifier) {
6843 return NULL;
6844 }
6845
6846 if (notifier->init()) {
6847 rc = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
6848 }
6849 if (rc != kIOReturnSuccess) {
6850 return NULL;
6851 }
6852
6853 notifier->ackTimeoutCnt = 0;
6854
6855 if (pmPowerStateQueue) {
6856 if (isSystemCapabilityClient) {
6857 notifier->retain();
6858 if (pmPowerStateQueue->submitPowerEvent(
6859 kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
6860 notifier->release();
6861 }
6862 }
6863
6864 if (isKernelCapabilityClient) {
6865 notifier->retain();
6866 if (pmPowerStateQueue->submitPowerEvent(
6867 kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
6868 notifier->release();
6869 }
6870 }
6871 }
6872
6873 OSSharedPtr<OSData> data;
6874 uint8_t *uuid = NULL;
6875 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
6876 if (kext) {
6877 data = kext->copyUUID();
6878 }
6879 if (data && (data->getLength() == sizeof(uuid_t))) {
6880 uuid = (uint8_t *)(data->getBytesNoCopy());
6881
6882 notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
6883 ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
6884 ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
6885 notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
6886 ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
6887 ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
6888
6889 notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
6890 }
6891 return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
6892 }
6893
6894 //******************************************************************************
6895 // systemMessageFilter
6896 //
6897 //******************************************************************************
6898
6899 bool
6900 IOPMrootDomain::systemMessageFilter(
6901 void * object, void * arg1, void * arg2, void * arg3 )
6902 {
6903 const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
6904 bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
6905 bool isCapClient = false;
6906 bool allow = false;
6907 IOPMServiceInterestNotifier *notifier;
6908
6909 notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
6910
6911 do {
6912 if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
6913 (!isCapMsg || !_joinedCapabilityClients ||
6914 !_joinedCapabilityClients->containsObject((OSObject *) object))) {
6915 break;
6916 }
6917
6918 // Capability change message for app and kernel clients.
6919
6920 if (isCapMsg) {
6921 // Kernel clients
6922 if ((context->notifyType == kNotifyPriority) ||
6923 (context->notifyType == kNotifyCapabilityChangePriority)) {
6924 isCapClient = true;
6925 }
6926
6927 // powerd's systemCapabilityNotifier
6928 if ((context->notifyType == kNotifyCapabilityChangeApps) &&
6929 (object == (void *) systemCapabilityNotifier.get())) {
6930 isCapClient = true;
6931 }
6932 }
6933
6934 if (isCapClient) {
6935 IOPMSystemCapabilityChangeParameters * capArgs =
6936 (IOPMSystemCapabilityChangeParameters *) arg2;
6937
6938 if (kSystemTransitionNewCapClient == _systemTransitionType) {
6939 capArgs->fromCapabilities = 0;
6940 capArgs->toCapabilities = _currentCapability;
6941 capArgs->changeFlags = 0;
6942 } else {
6943 capArgs->fromCapabilities = _currentCapability;
6944 capArgs->toCapabilities = _pendingCapability;
6945
6946 if (context->isPreChange) {
6947 capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
6948 } else {
6949 capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
6950 }
6951
6952 if ((object == (void *) systemCapabilityNotifier.get()) &&
6953 context->isPreChange) {
6954 toldPowerdCapWillChange = true;
6955 }
6956 }
6957
6958 // Capability change messages only go to the PM configd plugin.
6959 // Wait for response post-change if capabilitiy is increasing.
6960 // Wait for response pre-change if capability is decreasing.
6961
6962 if ((context->notifyType == kNotifyCapabilityChangeApps) && arg3 &&
6963 ((capabilityLoss && context->isPreChange) ||
6964 (!capabilityLoss && !context->isPreChange))) {
6965 // app has not replied yet, wait for it
6966 *((OSObject **) arg3) = kOSBooleanFalse;
6967 }
6968
6969 allow = true;
6970 break;
6971 }
6972
6973 // Capability client will always see kIOMessageCanSystemSleep,
6974 // even for demand sleep. It will also have a chance to veto
6975 // sleep one last time after all clients have responded to
6976 // kIOMessageSystemWillSleep
6977
6978 if ((kIOMessageCanSystemSleep == context->messageType) ||
6979 (kIOMessageSystemWillNotSleep == context->messageType)) {
6980 if (object == (OSObject *) systemCapabilityNotifier.get()) {
6981 allow = true;
6982 break;
6983 }
6984
6985 // Not idle sleep, don't ask apps.
6986 if (context->changeFlags & kIOPMSkipAskPowerDown) {
6987 break;
6988 }
6989 }
6990
6991 if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
6992 if ((object == (OSObject *) systemCapabilityNotifier.get()) &&
6993 CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
6994 (fullToDarkReason == kIOPMSleepReasonIdle)) {
6995 allow = true;
6996 }
6997 break;
6998 }
6999
7000 // Reject capability change messages for legacy clients.
7001 // Reject legacy system sleep messages for capability client.
7002
7003 if (isCapMsg || (object == (OSObject *) systemCapabilityNotifier.get())) {
7004 break;
7005 }
7006
7007 // Filter system sleep messages.
7008
7009 if ((context->notifyType == kNotifyApps) &&
7010 (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7011 allow = true;
7012
7013 if (notifier) {
7014 if (arg3) {
7015 if (notifier->ackTimeoutCnt >= 3) {
7016 *((OSObject **) arg3) = kOSBooleanFalse;
7017 } else {
7018 *((OSObject **) arg3) = kOSBooleanTrue;
7019 }
7020 }
7021 }
7022 } else if ((context->notifyType == kNotifyPriority) &&
7023 (_systemMessageClientMask & kSystemMessageClientKernel)) {
7024 allow = true;
7025 }
7026 }while (false);
7027
7028 if (allow && isCapMsg && _joinedCapabilityClients) {
7029 _joinedCapabilityClients->removeObject((OSObject *) object);
7030 if (_joinedCapabilityClients->getCount() == 0) {
7031 DLOG("destroyed capability client set %p\n",
7032 OBFUSCATE(_joinedCapabilityClients.get()));
7033 _joinedCapabilityClients.reset();
7034 }
7035 }
7036 if (notifier) {
7037 notifier->msgType = context->messageType;
7038 }
7039
7040 return allow;
7041 }
7042
7043 //******************************************************************************
7044 // setMaintenanceWakeCalendar
7045 //
7046 //******************************************************************************
7047
7048 IOReturn
7049 IOPMrootDomain::setMaintenanceWakeCalendar(
7050 const IOPMCalendarStruct * calendar )
7051 {
7052 OSSharedPtr<OSData> data;
7053 IOReturn ret = 0;
7054
7055 if (!calendar) {
7056 return kIOReturnBadArgument;
7057 }
7058
7059 data = OSData::withBytes((void *) calendar, sizeof(*calendar));
7060 if (!data) {
7061 return kIOReturnNoMemory;
7062 }
7063
7064 if (kPMCalendarTypeMaintenance == calendar->selector) {
7065 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get());
7066 } else if (kPMCalendarTypeSleepService == calendar->selector) {
7067 ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get());
7068 }
7069
7070 return ret;
7071 }
7072
7073 // MARK: -
7074 // MARK: Display Wrangler
7075
7076 //******************************************************************************
7077 // displayWranglerNotification
7078 //
7079 // Handle the notification when the IODisplayWrangler changes power state.
7080 //******************************************************************************
7081
7082 IOReturn
7083 IOPMrootDomain::displayWranglerNotification(
7084 void * target, void * refCon,
7085 UInt32 messageType, IOService * service,
7086 void * messageArgument, vm_size_t argSize )
7087 {
7088 #if DISPLAY_WRANGLER_PRESENT
7089 IOPMPowerStateIndex displayPowerState;
7090 IOPowerStateChangeNotification * params =
7091 (IOPowerStateChangeNotification *) messageArgument;
7092
7093 if ((messageType != kIOMessageDeviceWillPowerOff) &&
7094 (messageType != kIOMessageDeviceHasPoweredOn)) {
7095 return kIOReturnUnsupported;
7096 }
7097
7098 ASSERT_GATED();
7099 if (!gRootDomain) {
7100 return kIOReturnUnsupported;
7101 }
7102
7103 displayPowerState = params->stateNumber;
7104 DLOG("wrangler %s ps %d\n",
7105 getIOMessageString(messageType), (uint32_t) displayPowerState);
7106
7107 switch (messageType) {
7108 case kIOMessageDeviceWillPowerOff:
7109 // Display wrangler has dropped power due to display idle
7110 // or force system sleep.
7111 //
7112 // 4 Display ON kWranglerPowerStateMax
7113 // 3 Display Dim kWranglerPowerStateDim
7114 // 2 Display Sleep kWranglerPowerStateSleep
7115 // 1 Not visible to user
7116 // 0 Not visible to user kWranglerPowerStateMin
7117
7118 if (displayPowerState <= kWranglerPowerStateSleep) {
7119 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7120 }
7121 break;
7122
7123 case kIOMessageDeviceHasPoweredOn:
7124 // Display wrangler has powered on due to user activity
7125 // or wake from sleep.
7126
7127 if (kWranglerPowerStateMax == displayPowerState) {
7128 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7129
7130 // See comment in handleUpdatePowerClientForDisplayWrangler
7131 if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7132 kWranglerPowerStateMax) {
7133 gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7134 }
7135 }
7136 break;
7137 }
7138 #endif /* DISPLAY_WRANGLER_PRESENT */
7139 return kIOReturnUnsupported;
7140 }
7141
7142 //******************************************************************************
7143 // reportUserInput
7144 //
7145 //******************************************************************************
7146
7147 void
7148 IOPMrootDomain::updateUserActivity( void )
7149 {
7150 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7151 clock_get_uptime(&userActivityTime);
7152 bool aborting = ((lastSleepReason == kIOPMSleepReasonSoftware)
7153 || (lastSleepReason == kIOPMSleepReasonIdle)
7154 || (lastSleepReason == kIOPMSleepReasonMaintenance));
7155 if (aborting) {
7156 userActivityCount++;
7157 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7158 }
7159 #endif
7160 }
7161 void
7162 IOPMrootDomain::reportUserInput( void )
7163 {
7164 if (wrangler) {
7165 wrangler->activityTickle(0, 0);
7166 }
7167 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7168 // Update user activity
7169 updateUserActivity();
7170
7171 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7172 // update user active abs time
7173 clock_get_uptime(&gUserActiveAbsTime);
7174 pmPowerStateQueue->submitPowerEvent(
7175 kPowerEventPolicyStimulus,
7176 (void *) kStimulusDarkWakeActivityTickle,
7177 true /* set wake type */ );
7178 }
7179 #endif
7180 }
7181
7182 void
7183 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7184 {
7185 #if DISPLAY_WRANGLER_PRESENT
7186 if (wrangler) {
7187 wrangler->activityTickle(0, 0);
7188 }
7189 #else
7190 if (!device) {
7191 DLOG("requestUserActive: device is null\n");
7192 return;
7193 }
7194 OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7195 uint64_t registryID = device->getRegistryEntryID();
7196
7197 if (!deviceName || !registryID) {
7198 DLOG("requestUserActive: no device name or registry entry\n");
7199 return;
7200 }
7201 const char *name = deviceName->getCStringNoCopy();
7202 char payload[128];
7203 snprintf(payload, sizeof(payload), "%s:%s", name, reason);
7204 DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason);
7205 messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload));
7206 #endif
7207 }
7208
7209 //******************************************************************************
7210 // latchDisplayWranglerTickle
7211 //******************************************************************************
7212
7213 bool
7214 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7215 {
7216 #if DISPLAY_WRANGLER_PRESENT
7217 if (latch) {
7218 if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
7219 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7220 !checkSystemCanSustainFullWake()) {
7221 // Currently in dark wake, and not transitioning to full wake.
7222 // Full wake is unsustainable, so latch the tickle to prevent
7223 // the display from lighting up momentarily.
7224 wranglerTickled = true;
7225 } else {
7226 wranglerTickled = false;
7227 }
7228 } else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7229 wranglerTickled = false;
7230
7231 pmPowerStateQueue->submitPowerEvent(
7232 kPowerEventPolicyStimulus,
7233 (void *) kStimulusDarkWakeActivityTickle );
7234 }
7235
7236 return wranglerTickled;
7237 #else /* ! DISPLAY_WRANGLER_PRESENT */
7238 return false;
7239 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7240 }
7241
7242 //******************************************************************************
7243 // setDisplayPowerOn
7244 //
7245 // For root domain user client
7246 //******************************************************************************
7247
7248 void
7249 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7250 {
7251 pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7252 (void *) NULL, options );
7253 }
7254
7255 // MARK: -
7256 // MARK: System PM Policy
7257
7258 //******************************************************************************
7259 // checkSystemSleepAllowed
7260 //
7261 //******************************************************************************
7262
7263 bool
7264 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7265 uint32_t sleepReason )
7266 {
7267 uint32_t err = 0;
7268
7269 // Conditions that prevent idle and demand system sleep.
7270
7271 do {
7272 if (userDisabledAllSleep) {
7273 err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7274 break;
7275 }
7276
7277 if (systemBooting || systemShutdown || gWillShutdown) {
7278 err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7279 break;
7280 }
7281
7282 if (options == 0) {
7283 break;
7284 }
7285
7286 // Conditions above pegs the system at full wake.
7287 // Conditions below prevent system sleep but does not prevent
7288 // dark wake, and must be called from gated context.
7289
7290 #if !CONFIG_SLEEP
7291 err = kPMConfigPreventSystemSleep; // 3. config does not support sleep
7292 break;
7293 #endif
7294
7295 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7296 break; // always sleep on low battery or when in thermal warning/emergency state
7297 }
7298
7299 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7300 break; // always sleep on dark wake thermal emergencies
7301 }
7302
7303 if (preventSystemSleepList->getCount() != 0) {
7304 err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7305 break;
7306 }
7307
7308 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7309 kIOPMDriverAssertionLevelOn) {
7310 err = kPMCPUAssertion; // 5. CPU assertion
7311 break;
7312 }
7313
7314 if (pciCantSleepValid) {
7315 if (pciCantSleepFlag) {
7316 err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7317 }
7318 break;
7319 } else if (sleepSupportedPEFunction &&
7320 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7321 IOReturn ret;
7322 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7323 ret = getPlatform()->callPlatformFunction(
7324 sleepSupportedPEFunction.get(), false,
7325 NULL, NULL, NULL, NULL);
7326 pciCantSleepValid = true;
7327 pciCantSleepFlag = false;
7328 if ((platformSleepSupport & kPCICantSleep) ||
7329 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7330 err = 6; // 6. PCI card does not support PM
7331 pciCantSleepFlag = true;
7332 break;
7333 }
7334 }
7335 }while (false);
7336
7337 if (err) {
7338 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7339 return false;
7340 }
7341 return true;
7342 }
7343
7344 bool
7345 IOPMrootDomain::checkSystemSleepEnabled( void )
7346 {
7347 return checkSystemSleepAllowed(0, 0);
7348 }
7349
7350 bool
7351 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7352 {
7353 ASSERT_GATED();
7354 return checkSystemSleepAllowed(1, sleepReason);
7355 }
7356
7357 //******************************************************************************
7358 // checkSystemCanSustainFullWake
7359 //******************************************************************************
7360
7361 bool
7362 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7363 {
7364 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7365 // Low battery wake, or received a low battery notification
7366 // while system is awake. This condition will persist until
7367 // the following wake.
7368 return false;
7369 }
7370
7371 if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7372 // Graphics state is unknown and external display might not be probed.
7373 // Do not incorporate state that requires graphics to be in max power
7374 // such as desktopMode or clamshellDisabled.
7375
7376 if (!acAdaptorConnected) {
7377 DLOG("full wake check: no AC\n");
7378 return false;
7379 }
7380 }
7381 return true;
7382 }
7383
7384 //******************************************************************************
7385 // mustHibernate
7386 //******************************************************************************
7387
7388 #if HIBERNATION
7389
7390 bool
7391 IOPMrootDomain::mustHibernate( void )
7392 {
7393 return lowBatteryCondition || thermalWarningState;
7394 }
7395
7396 #endif /* HIBERNATION */
7397
7398 //******************************************************************************
7399 // AOT
7400 //******************************************************************************
7401
7402 // Tables for accumulated days in year by month, latter used for leap years
7403
7404 static const unsigned int daysbymonth[] =
7405 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7406
7407 static const unsigned int lydaysbymonth[] =
7408 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7409
7410 static int __unused
7411 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7412 {
7413 const unsigned int * dbm = daysbymonth;
7414 clock_sec_t n, x, y, z;
7415
7416 // Calculate seconds, minutes and hours
7417
7418 n = secs % (24 * 3600);
7419 dt->second = n % 60;
7420 n /= 60;
7421 dt->minute = n % 60;
7422 dt->hour = (typeof(dt->hour))(n / 60);
7423
7424 // Calculate day of week
7425
7426 n = secs / (24 * 3600);
7427 // dt->dayWeek = (n + 4) % 7;
7428
7429 // Calculate year
7430 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7431 // to days since 1/1/1968 to start on 4 year cycle, beginning
7432 // on a leap year.
7433
7434 n += (366 + 365);
7435
7436 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7437 // Valid before 2100, since 2100 is not a leap year.
7438
7439 x = n / 1461; // number of 4 year cycles
7440 y = n % 1461; // days into current 4 year cycle
7441 z = 1968 + (4 * x);
7442
7443 // Add in years in the current 4 year cycle
7444
7445 if (y >= 366) {
7446 y -= 366; // days after the leap year
7447 n = y % 365; // days into the current year
7448 z += (1 + y / 365); // years after the past 4-yr cycle
7449 } else {
7450 n = y;
7451 dbm = lydaysbymonth;
7452 }
7453 if (z > 2099) {
7454 return 0;
7455 }
7456
7457 dt->year = (typeof(dt->year))z;
7458
7459 // Adjust remaining days value to start at 1
7460
7461 n += 1;
7462
7463 // Calculate month
7464
7465 for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7466 continue;
7467 }
7468 dt->month = (typeof(dt->month))x;
7469
7470 // Calculate day of month
7471
7472 dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7473
7474 return 1;
7475 }
7476
7477 static clock_sec_t
7478 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7479 {
7480 const unsigned int * dbm = daysbymonth;
7481 long y, secs, days;
7482
7483 if (dt->year < 1970 || dt->month > 12) {
7484 return 0;
7485 }
7486
7487 // Seconds elapsed in the current day
7488
7489 secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7490
7491 // Number of days from 1/1/70 to beginning of current year
7492 // Account for extra day every 4 years starting at 1973
7493
7494 y = dt->year - 1970;
7495 days = (y * 365) + ((y + 1) / 4);
7496
7497 // Change table if current year is a leap year
7498
7499 if ((dt->year % 4) == 0) {
7500 dbm = lydaysbymonth;
7501 }
7502
7503 // Add in days elapsed in the current year
7504
7505 days += (dt->day - 1) + dbm[dt->month - 1];
7506
7507 // Add accumulated days to accumulated seconds
7508
7509 secs += 24 * 3600 * days;
7510
7511 return secs;
7512 }
7513
7514 unsigned long
7515 IOPMrootDomain::getRUN_STATE(void)
7516 {
7517 return _aotNow ? AOT_STATE : ON_STATE;
7518 }
7519
7520 bool
7521 IOPMrootDomain::isAOTMode()
7522 {
7523 return _aotNow;
7524 }
7525
7526 IOReturn
7527 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7528 {
7529 clock_sec_t nowsecs, wakesecs;
7530 clock_usec_t nowmicrosecs, wakemicrosecs;
7531 uint64_t nowAbs, wakeAbs;
7532
7533 clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
7534 wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
7535 if (wakeAbs < nowAbs) {
7536 printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
7537 wakeAbs = nowAbs;
7538 }
7539 wakeAbs -= nowAbs;
7540 absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7541
7542 wakesecs += nowsecs;
7543 wakemicrosecs += nowmicrosecs;
7544 if (wakemicrosecs >= USEC_PER_SEC) {
7545 wakesecs++;
7546 wakemicrosecs -= USEC_PER_SEC;
7547 }
7548 if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7549 wakesecs++;
7550 }
7551
7552 IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7553
7554 if (_aotWakeTimeContinuous != wakeContinuousTime) {
7555 _aotWakeTimeContinuous = wakeContinuousTime;
7556 IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7557 }
7558 _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7559 _aotWakeTimeUTC = wakesecs;
7560
7561 return kIOReturnSuccess;
7562 }
7563
7564 // assumes WAKEEVENT_LOCK
7565 bool
7566 IOPMrootDomain::aotShouldExit(bool checkTimeSet, bool software)
7567 {
7568 bool exitNow;
7569 const char * reason = "";
7570
7571 if (software) {
7572 _aotExit = true;
7573 _aotMetrics->softwareRequestCount++;
7574 reason = "software request";
7575 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7576 _aotExit = true;
7577 reason = gWakeReasonString;
7578 } else if (checkTimeSet && (kPMCalendarTypeInvalid == _aotWakeTimeCalendar.selector)) {
7579 _aotExit = true;
7580 _aotMetrics->noTimeSetCount++;
7581 reason = "flipbook expired";
7582 } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7583 clock_sec_t sec;
7584 clock_usec_t usec;
7585 clock_get_calendar_microtime(&sec, &usec);
7586 if (_calendarWakeAlarmUTC <= sec) {
7587 _aotExit = true;
7588 _aotMetrics->rtcAlarmsCount++;
7589 reason = "user alarm";
7590 }
7591 }
7592 exitNow = (_aotNow && _aotExit);
7593 if (exitNow) {
7594 _aotNow = false;
7595 IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7596 reason,
7597 _aotMetrics->sleepCount,
7598 _aotMetrics->possibleCount,
7599 _aotMetrics->confirmedPossibleCount,
7600 _aotMetrics->rejectedPossibleCount,
7601 _aotMetrics->expiredPossibleCount,
7602 _aotMetrics->noTimeSetCount,
7603 _aotMetrics->rtcAlarmsCount);
7604 }
7605 return exitNow;
7606 }
7607
7608 void
7609 IOPMrootDomain::aotExit(bool cps)
7610 {
7611 uint32_t savedMessageMask;
7612
7613 ASSERT_GATED();
7614 _aotTasksSuspended = false;
7615 _aotReadyToFullWake = false;
7616 if (_aotTimerScheduled) {
7617 _aotTimerES->cancelTimeout();
7618 _aotTimerScheduled = false;
7619 }
7620 updateTasksSuspend();
7621
7622 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7623 _aotLastWakeTime = 0;
7624 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7625 WAKEEVENT_LOCK();
7626 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7627 gWakeReasonString,
7628 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7629 WAKEEVENT_UNLOCK();
7630 }
7631
7632 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7633
7634 // Preserve the message mask since a system wake transition
7635 // may have already started and initialized the mask.
7636 savedMessageMask = _systemMessageClientMask;
7637 _systemMessageClientMask = kSystemMessageClientLegacyApp;
7638 tellClients(kIOMessageSystemWillPowerOn);
7639 _systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
7640
7641 if (cps) {
7642 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7643 }
7644 }
7645
7646 void
7647 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7648 {
7649 bool exitNow;
7650
7651 IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7652
7653 WAKEEVENT_LOCK();
7654 exitNow = aotShouldExit(false, false);
7655 if (timer != NULL) {
7656 _aotTimerScheduled = false;
7657 }
7658 WAKEEVENT_UNLOCK();
7659 if (exitNow) {
7660 aotExit(true);
7661 } else {
7662 #if 0
7663 if (_aotLingerTime) {
7664 uint64_t deadline;
7665 IOLog("aot linger before sleep\n");
7666 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7667 clock_delay_until(deadline);
7668 }
7669 #endif
7670 privateSleepSystem(kIOPMSleepReasonSoftware);
7671 }
7672 }
7673
7674 //******************************************************************************
7675 // adjustPowerState
7676 //
7677 // Conditions that affect our wake/sleep decision has changed.
7678 // If conditions dictate that the system must remain awake, clamp power
7679 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7680 // is TRUE, then remove the power clamp and allow the power state to drop
7681 // to SLEEP_STATE.
7682 //******************************************************************************
7683
7684 void
7685 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7686 {
7687 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7688 getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7689
7690 ASSERT_GATED();
7691
7692 if (_aotNow) {
7693 bool exitNow;
7694
7695 if (AOT_STATE != getPowerState()) {
7696 return;
7697 }
7698 WAKEEVENT_LOCK();
7699 exitNow = aotShouldExit(true, false);
7700 if (!exitNow
7701 && !_aotTimerScheduled
7702 && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
7703 _aotTimerScheduled = true;
7704 if (_aotLingerTime) {
7705 _aotTimerES->setTimeout(_aotLingerTime);
7706 } else {
7707 _aotTimerES->setTimeout(800, kMillisecondScale);
7708 }
7709 }
7710 WAKEEVENT_UNLOCK();
7711 if (exitNow) {
7712 aotExit(true);
7713 } else {
7714 _aotReadyToFullWake = true;
7715 if (!_aotTimerScheduled) {
7716 privateSleepSystem(kIOPMSleepReasonSoftware);
7717 }
7718 }
7719 return;
7720 }
7721
7722 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
7723 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
7724 } else if (sleepASAP) {
7725 changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
7726 }
7727 }
7728
7729 void
7730 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
7731 {
7732 if (powerOn) {
7733 if (!checkSystemCanSustainFullWake()) {
7734 DLOG("System cannot sustain full wake\n");
7735 return;
7736 }
7737
7738 // Force wrangler to max power state. If system is in dark wake
7739 // this alone won't raise the wrangler's power state.
7740 if (wrangler) {
7741 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
7742 }
7743
7744 // System in dark wake, always requesting full wake should
7745 // not have any bad side-effects, even if the request fails.
7746
7747 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
7748 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
7749 requestFullWake( kFullWakeReasonDisplayOn );
7750 }
7751 } else {
7752 // Relenquish desire to power up display.
7753 // Must first transition to state 1 since wrangler doesn't
7754 // power off the displays at state 0. At state 0 the root
7755 // domain is removed from the wrangler's power client list.
7756 if (wrangler) {
7757 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
7758 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
7759 }
7760 }
7761 }
7762
7763 //******************************************************************************
7764 // dispatchPowerEvent
7765 //
7766 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
7767 //******************************************************************************
7768
7769 void
7770 IOPMrootDomain::dispatchPowerEvent(
7771 uint32_t event, void * arg0, uint64_t arg1 )
7772 {
7773 ASSERT_GATED();
7774
7775 switch (event) {
7776 case kPowerEventFeatureChanged:
7777 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7778 messageClients(kIOPMMessageFeatureChange, this);
7779 break;
7780
7781 case kPowerEventReceivedPowerNotification:
7782 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7783 handlePowerNotification((UInt32)(uintptr_t) arg0 );
7784 break;
7785
7786 case kPowerEventSystemBootCompleted:
7787 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7788 if (systemBooting) {
7789 systemBooting = false;
7790
7791 // read noidle setting from Device Tree
7792 OSSharedPtr<IORegistryEntry> defaults = IORegistryEntry::fromPath("IODeviceTree:/defaults");
7793 if (defaults != NULL) {
7794 OSSharedPtr<OSObject> noIdleProp = defaults->copyProperty("no-idle");
7795 OSData *data = OSDynamicCast(OSData, noIdleProp.get());
7796 if ((data != NULL) && (data->getLength() == 4)) {
7797 gNoIdleFlag = *(uint32_t*)data->getBytesNoCopy();
7798 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
7799 }
7800 }
7801 if (lowBatteryCondition || thermalEmergencyState) {
7802 if (lowBatteryCondition) {
7803 privateSleepSystem(kIOPMSleepReasonLowPower);
7804 } else {
7805 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
7806 }
7807 // The rest is unnecessary since the system is expected
7808 // to sleep immediately. The following wake will update
7809 // everything.
7810 break;
7811 }
7812
7813 sleepWakeDebugMemAlloc();
7814 saveFailureData2File();
7815
7816 // If lid is closed, re-send lid closed notification
7817 // now that booting is complete.
7818 if (clamshellClosed) {
7819 handlePowerNotification(kLocalEvalClamshellCommand);
7820 }
7821 evaluatePolicy( kStimulusAllowSystemSleepChanged );
7822 }
7823 break;
7824
7825 case kPowerEventSystemShutdown:
7826 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7827 if (kOSBooleanTrue == (OSBoolean *) arg0) {
7828 /* We set systemShutdown = true during shutdown
7829 * to prevent sleep at unexpected times while loginwindow is trying
7830 * to shutdown apps and while the OS is trying to transition to
7831 * complete power of.
7832 *
7833 * Set to true during shutdown, as soon as loginwindow shows
7834 * the "shutdown countdown dialog", through individual app
7835 * termination, and through black screen kernel shutdown.
7836 */
7837 systemShutdown = true;
7838 } else {
7839 /*
7840 * A shutdown was initiated, but then the shutdown
7841 * was cancelled, clearing systemShutdown to false here.
7842 */
7843 systemShutdown = false;
7844 }
7845 break;
7846
7847 case kPowerEventUserDisabledSleep:
7848 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7849 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
7850 break;
7851
7852 case kPowerEventRegisterSystemCapabilityClient:
7853 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7854
7855 // reset() handles the arg0 == nullptr case for us
7856 systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
7857 /* intentional fall-through */
7858 [[clang::fallthrough]];
7859
7860 case kPowerEventRegisterKernelCapabilityClient:
7861 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7862 if (!_joinedCapabilityClients) {
7863 _joinedCapabilityClients = OSSet::withCapacity(8);
7864 }
7865 if (arg0) {
7866 OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
7867 if (_joinedCapabilityClients) {
7868 _joinedCapabilityClients->setObject(notify.get());
7869 synchronizePowerTree( kIOPMSyncNoChildNotify );
7870 }
7871 }
7872 break;
7873
7874 case kPowerEventPolicyStimulus:
7875 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7876 if (arg0) {
7877 int stimulus = (int)(uintptr_t) arg0;
7878 evaluatePolicy(stimulus, (uint32_t) arg1);
7879 }
7880 break;
7881
7882 case kPowerEventAssertionCreate:
7883 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7884 if (pmAssertions) {
7885 pmAssertions->handleCreateAssertion((OSData *)arg0);
7886 }
7887 break;
7888
7889
7890 case kPowerEventAssertionRelease:
7891 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7892 if (pmAssertions) {
7893 pmAssertions->handleReleaseAssertion(arg1);
7894 }
7895 break;
7896
7897 case kPowerEventAssertionSetLevel:
7898 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7899 if (pmAssertions) {
7900 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
7901 }
7902 break;
7903
7904 case kPowerEventQueueSleepWakeUUID:
7905 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7906 handleQueueSleepWakeUUID((OSObject *)arg0);
7907 break;
7908 case kPowerEventPublishSleepWakeUUID:
7909 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7910 handlePublishSleepWakeUUID((bool)arg0);
7911 break;
7912
7913 case kPowerEventSetDisplayPowerOn:
7914 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7915 if (arg1 != 0) {
7916 displayPowerOnRequested = true;
7917 } else {
7918 displayPowerOnRequested = false;
7919 }
7920 handleSetDisplayPowerOn(displayPowerOnRequested);
7921 break;
7922
7923 case kPowerEventPublishWakeType:
7924 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7925
7926 // Don't replace wake type property if already set
7927 if ((arg0 == gIOPMWakeTypeUserKey) ||
7928 !propertyExists(kIOPMRootDomainWakeTypeKey)) {
7929 const char * wakeType = NULL;
7930
7931 if (arg0 == gIOPMWakeTypeUserKey) {
7932 requestUserActive(this, "WakeTypeUser");
7933 wakeType = kIOPMRootDomainWakeTypeUser;
7934 } else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
7935 requestUserActive(this, "WakeTypeAlarm");
7936 wakeType = kIOPMRootDomainWakeTypeAlarm;
7937 } else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
7938 darkWakeSleepService = true;
7939 wakeType = kIOPMRootDomainWakeTypeSleepService;
7940 } else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
7941 wakeType = kIOPMRootDomainWakeTypeMaintenance;
7942 }
7943
7944 if (wakeType) {
7945 setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
7946 }
7947 }
7948 break;
7949
7950 case kPowerEventAOTEvaluate:
7951 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7952 if (_aotReadyToFullWake) {
7953 aotEvaluate(NULL);
7954 }
7955 break;
7956 }
7957 }
7958
7959 //******************************************************************************
7960 // systemPowerEventOccurred
7961 //
7962 // The power controller is notifying us of a hardware-related power management
7963 // event that we must handle.
7964 //
7965 // systemPowerEventOccurred covers the same functionality that
7966 // receivePowerNotification does; it simply provides a richer API for conveying
7967 // more information.
7968 //******************************************************************************
7969
7970 IOReturn
7971 IOPMrootDomain::systemPowerEventOccurred(
7972 const OSSymbol *event,
7973 uint32_t intValue)
7974 {
7975 IOReturn attempt = kIOReturnSuccess;
7976 OSSharedPtr<OSNumber> newNumber;
7977
7978 if (!event) {
7979 return kIOReturnBadArgument;
7980 }
7981
7982 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
7983 if (!newNumber) {
7984 return kIOReturnInternalError;
7985 }
7986
7987 attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
7988
7989 return attempt;
7990 }
7991
7992 void
7993 IOPMrootDomain::setThermalState(OSObject *value)
7994 {
7995 OSNumber * num;
7996
7997 if (gIOPMWorkLoop->inGate() == false) {
7998 gIOPMWorkLoop->runAction(
7999 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8000 (OSObject *)this,
8001 (void *)value);
8002
8003 return;
8004 }
8005 if (value && (num = OSDynamicCast(OSNumber, value))) {
8006 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8007 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8008 }
8009 }
8010
8011 IOReturn
8012 IOPMrootDomain::systemPowerEventOccurred(
8013 const OSSymbol *event,
8014 OSObject *value)
8015 {
8016 OSSharedPtr<OSDictionary> thermalsDict;
8017 bool shouldUpdate = true;
8018
8019 if (!event || !value) {
8020 return kIOReturnBadArgument;
8021 }
8022
8023 // LOCK
8024 // We reuse featuresDict Lock because it already exists and guards
8025 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
8026 // of stepping on that lock.
8027 if (featuresDictLock) {
8028 IOLockLock(featuresDictLock);
8029 }
8030
8031 OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8032 OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8033
8034 if (origThermalsDict) {
8035 thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8036 } else {
8037 thermalsDict = OSDictionary::withCapacity(1);
8038 }
8039
8040 if (!thermalsDict) {
8041 shouldUpdate = false;
8042 goto exit;
8043 }
8044
8045 thermalsDict->setObject(event, value);
8046
8047 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8048
8049 exit:
8050 // UNLOCK
8051 if (featuresDictLock) {
8052 IOLockUnlock(featuresDictLock);
8053 }
8054
8055 if (shouldUpdate) {
8056 if (event &&
8057 event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8058 setThermalState(value);
8059 }
8060 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8061 }
8062
8063 return kIOReturnSuccess;
8064 }
8065
8066 //******************************************************************************
8067 // receivePowerNotification
8068 //
8069 // The power controller is notifying us of a hardware-related power management
8070 // event that we must handle. This may be a result of an 'environment' interrupt
8071 // from the power mgt micro.
8072 //******************************************************************************
8073
8074 IOReturn
8075 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8076 {
8077 if (msg & kIOPMPowerButton) {
8078 uint32_t currentPhase = pmTracer->getTracePhase();
8079 if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8080 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8081 swd_flags |= SWD_PWR_BTN_STACKSHOT;
8082 thread_call_enter(powerButtonDown);
8083 } else {
8084 DEBUG_LOG("power button pressed when system is up\n");
8085 }
8086 } else if (msg & kIOPMPowerButtonUp) {
8087 if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8088 swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8089 thread_call_enter(powerButtonUp);
8090 }
8091 } else {
8092 pmPowerStateQueue->submitPowerEvent(
8093 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8094 }
8095 return kIOReturnSuccess;
8096 }
8097
8098 void
8099 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8100 {
8101 bool eval_clamshell = false;
8102 bool eval_clamshell_alarm = false;
8103
8104 ASSERT_GATED();
8105
8106 /*
8107 * Local (IOPMrootDomain only) eval clamshell command
8108 */
8109 if (msg & kLocalEvalClamshellCommand) {
8110 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8111 eval_clamshell_alarm = true;
8112
8113 // reset isRTCAlarmWake. This evaluation should happen only once
8114 // on RTC/Alarm wake. Any clamshell events after wake should follow
8115 // the regular evaluation
8116 isRTCAlarmWake = false;
8117 } else {
8118 eval_clamshell = true;
8119 }
8120 }
8121
8122 /*
8123 * Overtemp
8124 */
8125 if (msg & kIOPMOverTemp) {
8126 DLOG("Thermal overtemp message received!\n");
8127 thermalEmergencyState = true;
8128 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8129 }
8130
8131 /*
8132 * Forward DW thermal notification to client, if system is not going to sleep
8133 */
8134 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8135 DLOG("DarkWake thermal limits message received!\n");
8136 messageClients(kIOPMMessageDarkWakeThermalEmergency);
8137 }
8138
8139 /*
8140 * Sleep Now!
8141 */
8142 if (msg & kIOPMSleepNow) {
8143 privateSleepSystem(kIOPMSleepReasonSoftware);
8144 }
8145
8146 /*
8147 * Power Emergency
8148 */
8149 if (msg & kIOPMPowerEmergency) {
8150 DLOG("Low battery notification received\n");
8151 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8152 // Wait for the next low battery notification if the system state is
8153 // in transition.
8154 if ((_systemTransitionType == kSystemTransitionNone) &&
8155 CAP_CURRENT(kIOPMSystemCapabilityCPU) &&
8156 !systemBooting && !systemShutdown && !gWillShutdown) {
8157 // Setting lowBatteryCondition will prevent system sleep
8158 lowBatteryCondition = true;
8159
8160 // Notify userspace to initiate system shutdown
8161 messageClients(kIOPMMessageRequestSystemShutdown);
8162 }
8163 #else
8164 lowBatteryCondition = true;
8165 privateSleepSystem(kIOPMSleepReasonLowPower);
8166 #endif
8167 }
8168
8169 /*
8170 * Clamshell OPEN
8171 */
8172 if (msg & kIOPMClamshellOpened) {
8173 DLOG("Clamshell opened\n");
8174 // Received clamshel open message from clamshell controlling driver
8175 // Update our internal state and tell general interest clients
8176 clamshellClosed = false;
8177 clamshellExists = true;
8178
8179 // Don't issue a hid tickle when lid is open and polled on wake
8180 if (msg & kIOPMSetValue) {
8181 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8182 reportUserInput();
8183 }
8184
8185 // Tell PMCPU
8186 informCPUStateChange(kInformLid, 0);
8187
8188 // Tell general interest clients
8189 sendClientClamshellNotification();
8190
8191 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
8192 || (lastSleepReason == kIOPMSleepReasonIdle)
8193 || (lastSleepReason == kIOPMSleepReasonMaintenance));
8194 if (aborting) {
8195 userActivityCount++;
8196 }
8197 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8198 }
8199
8200 /*
8201 * Clamshell CLOSED
8202 * Send the clamshell interest notification since the lid is closing.
8203 */
8204 if (msg & kIOPMClamshellClosed) {
8205 if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8206 clamshellClosed && clamshellExists) {
8207 DLOG("Ignoring redundant Clamshell close event\n");
8208 } else {
8209 DLOG("Clamshell closed\n");
8210 // Received clamshel open message from clamshell controlling driver
8211 // Update our internal state and tell general interest clients
8212 clamshellClosed = true;
8213 clamshellExists = true;
8214
8215 // Ignore all following clamshell close events until the clamshell
8216 // is opened or the system sleeps. When a clamshell close triggers
8217 // a system wake, the lid driver may send us two clamshell close
8218 // events, one for the clamshell close event itself, and a second
8219 // close event when the driver polls the lid state on wake.
8220 clamshellIgnoreClose = true;
8221
8222 // Tell PMCPU
8223 informCPUStateChange(kInformLid, 1);
8224
8225 // Tell general interest clients
8226 sendClientClamshellNotification();
8227
8228 // And set eval_clamshell = so we can attempt
8229 eval_clamshell = true;
8230 }
8231 }
8232
8233 /*
8234 * Set Desktop mode (sent from graphics)
8235 *
8236 * -> reevaluate lid state
8237 */
8238 if (msg & kIOPMSetDesktopMode) {
8239 desktopMode = (0 != (msg & kIOPMSetValue));
8240 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8241 DLOG("Desktop mode %d\n", desktopMode);
8242
8243 sendClientClamshellNotification();
8244
8245 // Re-evaluate the lid state
8246 eval_clamshell = true;
8247 }
8248
8249 /*
8250 * AC Adaptor connected
8251 *
8252 * -> reevaluate lid state
8253 */
8254 if (msg & kIOPMSetACAdaptorConnected) {
8255 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8256 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8257
8258 // Tell CPU PM
8259 informCPUStateChange(kInformAC, !acAdaptorConnected);
8260
8261 // Tell BSD if AC is connected
8262 // 0 == external power source; 1 == on battery
8263 post_sys_powersource(acAdaptorConnected ? 0:1);
8264
8265 sendClientClamshellNotification();
8266
8267 // Re-evaluate the lid state
8268 eval_clamshell = true;
8269
8270 // Lack of AC may have latched a display wrangler tickle.
8271 // This mirrors the hardware's USB wake event latch, where a latched
8272 // USB wake event followed by an AC attach will trigger a full wake.
8273 latchDisplayWranglerTickle( false );
8274
8275 #if HIBERNATION
8276 // AC presence will reset the standy timer delay adjustment.
8277 _standbyTimerResetSeconds = 0;
8278 #endif
8279 if (!userIsActive) {
8280 // Reset userActivityTime when power supply is changed(rdr 13789330)
8281 clock_get_uptime(&userActivityTime);
8282 }
8283 }
8284
8285 /*
8286 * Enable Clamshell (external display disappear)
8287 *
8288 * -> reevaluate lid state
8289 */
8290 if (msg & kIOPMEnableClamshell) {
8291 DLOG("Clamshell enabled\n");
8292
8293 // Re-evaluate the lid state
8294 // System should sleep on external display disappearance
8295 // in lid closed operation.
8296 if (true == clamshellDisabled) {
8297 eval_clamshell = true;
8298
8299 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8300 // Also clear kClamshellSleepDisableInternal when graphics enables
8301 // the clamshell during a full wake. When graphics is behaving as
8302 // expected, this will allow clamshell close to be honored earlier
8303 // rather than waiting for the delayed evaluation.
8304 if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8305 (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8306 CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8307 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8308
8309 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8310 // when timer expires which is harmless but useless.
8311 thread_call_cancel(fullWakeThreadCall);
8312 }
8313 #endif
8314 }
8315
8316 clamshellDisabled = false;
8317 sendClientClamshellNotification();
8318 }
8319
8320 /*
8321 * Disable Clamshell (external display appeared)
8322 * We don't bother re-evaluating clamshell state. If the system is awake,
8323 * the lid is probably open.
8324 */
8325 if (msg & kIOPMDisableClamshell) {
8326 DLOG("Clamshell disabled\n");
8327 clamshellDisabled = true;
8328 sendClientClamshellNotification();
8329 }
8330
8331 /*
8332 * Evaluate clamshell and SLEEP if appropriate
8333 */
8334 if (eval_clamshell_alarm && clamshellClosed) {
8335 if (shouldSleepOnRTCAlarmWake()) {
8336 privateSleepSystem(kIOPMSleepReasonClamshell);
8337 }
8338 } else if (eval_clamshell && clamshellClosed) {
8339 if (shouldSleepOnClamshellClosed()) {
8340 privateSleepSystem(kIOPMSleepReasonClamshell);
8341 } else {
8342 evaluatePolicy( kStimulusDarkWakeEvaluate );
8343 }
8344 }
8345
8346 if (msg & kIOPMProModeEngaged) {
8347 int newState = 1;
8348 DLOG("ProModeEngaged\n");
8349 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8350 }
8351
8352 if (msg & kIOPMProModeDisengaged) {
8353 int newState = 0;
8354 DLOG("ProModeDisengaged\n");
8355 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8356 }
8357 }
8358
8359 //******************************************************************************
8360 // evaluatePolicy
8361 //
8362 // Evaluate root-domain policy in response to external changes.
8363 //******************************************************************************
8364
8365 void
8366 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8367 {
8368 union {
8369 struct {
8370 int idleSleepEnabled : 1;
8371 int idleSleepDisabled : 1;
8372 int displaySleep : 1;
8373 int sleepDelayChanged : 1;
8374 int evaluateDarkWake : 1;
8375 int adjustPowerState : 1;
8376 int userBecameInactive : 1;
8377 int displaySleepEntry : 1;
8378 } bit;
8379 uint32_t u32;
8380 } flags;
8381
8382
8383 ASSERT_GATED();
8384 flags.u32 = 0;
8385
8386 switch (stimulus) {
8387 case kStimulusDisplayWranglerSleep:
8388 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8389 if (!wranglerPowerOff) {
8390 // wrangler is in sleep state or lower
8391 flags.bit.displaySleep = true;
8392 }
8393 if (!wranglerAsleep) {
8394 // transition from wrangler wake to wrangler sleep
8395 flags.bit.displaySleepEntry = true;
8396 wranglerAsleep = true;
8397 }
8398 break;
8399
8400 case kStimulusDisplayWranglerWake:
8401 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8402 displayIdleForDemandSleep = false;
8403 wranglerPowerOff = false;
8404 wranglerAsleep = false;
8405 break;
8406
8407 case kStimulusEnterUserActiveState:
8408 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8409 if (_preventUserActive) {
8410 DLOG("user active dropped\n");
8411 break;
8412 }
8413 if (!userIsActive) {
8414 userIsActive = true;
8415 userWasActive = true;
8416 clock_get_uptime(&gUserActiveAbsTime);
8417
8418 // Stay awake after dropping demand for display power on
8419 if (kFullWakeReasonDisplayOn == fullWakeReason) {
8420 fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8421 DLOG("User activity while in notification wake\n");
8422 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8423 }
8424
8425 kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8426 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8427 messageClients(kIOPMMessageUserIsActiveChanged);
8428 }
8429 flags.bit.idleSleepDisabled = true;
8430 break;
8431
8432 case kStimulusLeaveUserActiveState:
8433 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8434 if (userIsActive) {
8435 clock_get_uptime(&gUserInactiveAbsTime);
8436 userIsActive = false;
8437 clock_get_uptime(&userBecameInactiveTime);
8438 flags.bit.userBecameInactive = true;
8439
8440 kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8441 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8442 messageClients(kIOPMMessageUserIsActiveChanged);
8443 }
8444 break;
8445
8446 case kStimulusAggressivenessChanged:
8447 {
8448 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8449 unsigned long aggressiveValue;
8450 uint32_t minutesToIdleSleep = 0;
8451 uint32_t minutesToDisplayDim = 0;
8452 uint32_t minutesDelta = 0;
8453
8454 // Fetch latest display and system sleep slider values.
8455 aggressiveValue = 0;
8456 getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8457 minutesToIdleSleep = (uint32_t) aggressiveValue;
8458
8459 aggressiveValue = 0;
8460 getAggressiveness(kPMMinutesToDim, &aggressiveValue);
8461 minutesToDisplayDim = (uint32_t) aggressiveValue;
8462 DLOG("aggressiveness changed: system %u->%u, display %u\n",
8463 sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
8464
8465 DLOG("idle time -> %d secs (ena %d)\n",
8466 idleSeconds, (minutesToIdleSleep != 0));
8467
8468 // How long to wait before sleeping the system once
8469 // the displays turns off is indicated by 'extraSleepDelay'.
8470
8471 if (minutesToIdleSleep > minutesToDisplayDim) {
8472 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8473 } else if (minutesToIdleSleep == minutesToDisplayDim) {
8474 minutesDelta = 1;
8475 }
8476
8477 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8478 idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8479 }
8480
8481 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8482 flags.bit.idleSleepDisabled = true;
8483 idleSleepEnabled = false;
8484 }
8485 #if !defined(XNU_TARGET_OS_OSX)
8486 if (0x7fffffff == minutesToIdleSleep) {
8487 minutesToIdleSleep = idleSeconds;
8488 }
8489 #endif /* !defined(XNU_TARGET_OS_OSX) */
8490
8491 if (((minutesDelta != extraSleepDelay) ||
8492 (userActivityTime != userActivityTime_prev)) &&
8493 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8494 flags.bit.sleepDelayChanged = true;
8495 }
8496
8497 if (systemDarkWake && !darkWakeToSleepASAP &&
8498 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8499 // Reconsider decision to remain in dark wake
8500 flags.bit.evaluateDarkWake = true;
8501 }
8502
8503 sleepSlider = minutesToIdleSleep;
8504 extraSleepDelay = minutesDelta;
8505 userActivityTime_prev = userActivityTime;
8506 } break;
8507
8508 case kStimulusDemandSystemSleep:
8509 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8510 displayIdleForDemandSleep = true;
8511 if (wrangler && wranglerIdleSettings) {
8512 // Request wrangler idle only when demand sleep is triggered
8513 // from full wake.
8514 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8515 wrangler->setProperties(wranglerIdleSettings.get());
8516 DLOG("Requested wrangler idle\n");
8517 }
8518 }
8519 // arg = sleepReason
8520 changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8521 break;
8522
8523 case kStimulusAllowSystemSleepChanged:
8524 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8525 flags.bit.adjustPowerState = true;
8526 break;
8527
8528 case kStimulusDarkWakeActivityTickle:
8529 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8530 // arg == true implies real and not self generated wrangler tickle.
8531 // Update wake type on PM work loop instead of the tickle thread to
8532 // eliminate the possibility of an early tickle clobbering the wake
8533 // type set by the platform driver.
8534 if (arg == true) {
8535 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8536 }
8537
8538 if (!darkWakeExit) {
8539 if (latchDisplayWranglerTickle(true)) {
8540 DLOG("latched tickle\n");
8541 break;
8542 }
8543
8544 darkWakeExit = true;
8545 DLOG("Requesting full wake due to dark wake activity tickle\n");
8546 requestFullWake( kFullWakeReasonLocalUser );
8547 }
8548 break;
8549
8550 case kStimulusDarkWakeEntry:
8551 case kStimulusDarkWakeReentry:
8552 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8553 // Any system transitions since the last dark wake transition
8554 // will invalid the stimulus.
8555
8556 if (arg == _systemStateGeneration) {
8557 DLOG("dark wake entry\n");
8558 systemDarkWake = true;
8559
8560 // Keep wranglerPowerOff an invariant when wrangler is absent
8561 if (wrangler) {
8562 wranglerPowerOff = true;
8563 }
8564
8565 if (kStimulusDarkWakeEntry == stimulus) {
8566 clock_get_uptime(&userBecameInactiveTime);
8567 flags.bit.evaluateDarkWake = true;
8568 if (activitySinceSleep()) {
8569 DLOG("User activity recorded while going to darkwake\n");
8570 reportUserInput();
8571 }
8572 }
8573
8574 // Always accelerate disk spindown while in dark wake,
8575 // even if system does not support/allow sleep.
8576
8577 cancelIdleSleepTimer();
8578 setQuickSpinDownTimeout();
8579 }
8580 break;
8581
8582 case kStimulusDarkWakeEvaluate:
8583 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8584 if (systemDarkWake) {
8585 flags.bit.evaluateDarkWake = true;
8586 }
8587 break;
8588
8589 case kStimulusNoIdleSleepPreventers:
8590 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8591 flags.bit.adjustPowerState = true;
8592 break;
8593 } /* switch(stimulus) */
8594
8595 if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
8596 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8597 darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
8598 if (darkWakeToSleepASAP ||
8599 (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
8600 uint32_t newSleepReason;
8601
8602 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8603 // System was previously in full wake. Sleep reason from
8604 // full to dark already recorded in fullToDarkReason.
8605
8606 if (lowBatteryCondition) {
8607 newSleepReason = kIOPMSleepReasonLowPower;
8608 } else if (thermalEmergencyState) {
8609 newSleepReason = kIOPMSleepReasonThermalEmergency;
8610 } else {
8611 newSleepReason = fullToDarkReason;
8612 }
8613 } else {
8614 // In dark wake from system sleep.
8615
8616 if (darkWakeSleepService) {
8617 newSleepReason = kIOPMSleepReasonSleepServiceExit;
8618 } else {
8619 newSleepReason = kIOPMSleepReasonMaintenance;
8620 }
8621 }
8622
8623 if (checkSystemCanSleep(newSleepReason)) {
8624 privateSleepSystem(newSleepReason);
8625 }
8626 } else { // non-maintenance (network) dark wake
8627 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8628 // Release power clamp, and wait for children idle.
8629 adjustPowerState(true);
8630 } else {
8631 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8632 }
8633 }
8634 }
8635
8636 if (systemDarkWake) {
8637 // The rest are irrelevant while system is in dark wake.
8638 flags.u32 = 0;
8639 }
8640
8641 if ((flags.bit.displaySleepEntry) &&
8642 (kFullWakeReasonDisplayOn == fullWakeReason)) {
8643 // kIOPMSleepReasonNotificationWakeExit
8644 DLOG("Display sleep while in notification wake\n");
8645 changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8646 }
8647
8648 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8649 bool cancelQuickSpindown = false;
8650
8651 if (flags.bit.sleepDelayChanged) {
8652 // Cancel existing idle sleep timer and quick disk spindown.
8653 // New settings will be applied by the idleSleepEnabled flag
8654 // handler below if idle sleep is enabled.
8655
8656 DLOG("extra sleep timer changed\n");
8657 cancelIdleSleepTimer();
8658 cancelQuickSpindown = true;
8659 } else {
8660 DLOG("user inactive\n");
8661 }
8662
8663 if (!userIsActive && idleSleepEnabled) {
8664 startIdleSleepTimer(getTimeToIdleSleep());
8665 }
8666
8667 if (cancelQuickSpindown) {
8668 restoreUserSpinDownTimeout();
8669 }
8670 }
8671
8672 if (flags.bit.idleSleepEnabled) {
8673 DLOG("idle sleep timer enabled\n");
8674 if (!wrangler) {
8675 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8676 startIdleSleepTimer(getTimeToIdleSleep());
8677 #else
8678 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8679 startIdleSleepTimer( idleSeconds );
8680 #endif
8681 } else {
8682 // Start idle timer if prefs now allow system sleep
8683 // and user is already inactive. Disk spindown is
8684 // accelerated upon timer expiration.
8685
8686 if (!userIsActive) {
8687 startIdleSleepTimer(getTimeToIdleSleep());
8688 }
8689 }
8690 }
8691
8692 if (flags.bit.idleSleepDisabled) {
8693 DLOG("idle sleep timer disabled\n");
8694 cancelIdleSleepTimer();
8695 restoreUserSpinDownTimeout();
8696 adjustPowerState();
8697 }
8698
8699 if (flags.bit.adjustPowerState) {
8700 bool sleepASAP = false;
8701
8702 if (!systemBooting && (0 == idleSleepPreventersCount())) {
8703 if (!wrangler) {
8704 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
8705 if (idleSleepEnabled) {
8706 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8707 if (!extraSleepDelay && !idleSleepTimerPending) {
8708 sleepASAP = true;
8709 }
8710 #else
8711 // stay awake for at least idleSeconds
8712 startIdleSleepTimer(idleSeconds);
8713 #endif
8714 }
8715 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake) {
8716 sleepASAP = true;
8717 }
8718 }
8719
8720 adjustPowerState(sleepASAP);
8721 }
8722 }
8723
8724 //******************************************************************************
8725
8726 unsigned int
8727 IOPMrootDomain::idleSleepPreventersCount()
8728 {
8729 if (_aotMode) {
8730 unsigned int count __block;
8731 count = 0;
8732 preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
8733 {
8734 count += (NULL == obj->metaCast("AppleARMBacklight"));
8735 return false;
8736 });
8737 return count;
8738 }
8739
8740 return preventIdleSleepList->getCount();
8741 }
8742
8743
8744 //******************************************************************************
8745 // requestFullWake
8746 //
8747 // Request transition from dark wake to full wake
8748 //******************************************************************************
8749
8750 void
8751 IOPMrootDomain::requestFullWake( FullWakeReason reason )
8752 {
8753 uint32_t options = 0;
8754 IOService * pciRoot = NULL;
8755 bool promotion = false;
8756
8757 // System must be in dark wake and a valid reason for entering full wake
8758 if ((kFullWakeReasonNone == reason) ||
8759 (kFullWakeReasonNone != fullWakeReason) ||
8760 (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8761 return;
8762 }
8763
8764 // Will clear reason upon exit from full wake
8765 fullWakeReason = reason;
8766
8767 _desiredCapability |= (kIOPMSystemCapabilityGraphics |
8768 kIOPMSystemCapabilityAudio);
8769
8770 if ((kSystemTransitionWake == _systemTransitionType) &&
8771 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
8772 !darkWakePowerClamped) {
8773 // Promote to full wake while waking up to dark wake due to tickle.
8774 // PM will hold off notifying the graphics subsystem about system wake
8775 // as late as possible, so if a HID tickle does arrive, graphics can
8776 // power up from this same wake transition. Otherwise, the latency to
8777 // power up graphics on the following transition can be huge on certain
8778 // systems. However, once any power clamping has taken effect, it is
8779 // too late to promote the current dark wake transition to a full wake.
8780 _pendingCapability |= (kIOPMSystemCapabilityGraphics |
8781 kIOPMSystemCapabilityAudio);
8782
8783 // Tell the PCI parent of audio and graphics drivers to stop
8784 // delaying the child notifications. Same for root domain.
8785 pciRoot = pciHostBridgeDriver.get();
8786 willEnterFullWake();
8787 promotion = true;
8788 }
8789
8790 // Unsafe to cancel once graphics was powered.
8791 // If system woke from dark wake, the return to sleep can
8792 // be cancelled. "awake -> dark -> sleep" transition
8793 // can be cancelled also, during the "dark -> sleep" phase
8794 // *prior* to driver power down.
8795 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
8796 _pendingCapability == 0) {
8797 options |= kIOPMSyncCancelPowerDown;
8798 }
8799
8800 synchronizePowerTree(options, pciRoot);
8801
8802 if (kFullWakeReasonLocalUser == fullWakeReason) {
8803 // IOGraphics doesn't light the display even though graphics is
8804 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
8805 // So, do an explicit activity tickle
8806 if (wrangler) {
8807 wrangler->activityTickle(0, 0);
8808 }
8809 }
8810
8811 // Log a timestamp for the initial full wake request.
8812 // System may not always honor this full wake request.
8813 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8814 AbsoluteTime now;
8815 uint64_t nsec;
8816
8817 clock_get_uptime(&now);
8818 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
8819 absolutetime_to_nanoseconds(now, &nsec);
8820 MSG("full wake %s (reason %u) %u ms\n",
8821 promotion ? "promotion" : "request",
8822 fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
8823 }
8824 }
8825
8826 //******************************************************************************
8827 // willEnterFullWake
8828 //
8829 // System will enter full wake from sleep, from dark wake, or from dark
8830 // wake promotion. This function aggregate things that are in common to
8831 // all three full wake transitions.
8832 //
8833 // Assumptions: fullWakeReason was updated
8834 //******************************************************************************
8835
8836 void
8837 IOPMrootDomain::willEnterFullWake( void )
8838 {
8839 hibernateRetry = false;
8840 sleepToStandby = false;
8841 standbyNixed = false;
8842 resetTimers = false;
8843 sleepTimerMaintenance = false;
8844
8845 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
8846
8847 _systemMessageClientMask = kSystemMessageClientPowerd |
8848 kSystemMessageClientLegacyApp;
8849
8850 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
8851 // First time to attain full wake capability since the last wake
8852 _systemMessageClientMask |= kSystemMessageClientKernel;
8853
8854 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
8855 setProperty(gIOPMUserTriggeredFullWakeKey.get(),
8856 (kFullWakeReasonLocalUser == fullWakeReason) ?
8857 kOSBooleanTrue : kOSBooleanFalse);
8858 }
8859 #if HIBERNATION
8860 IOHibernateSetWakeCapabilities(_pendingCapability);
8861 #endif
8862
8863 IOService::setAdvisoryTickleEnable( true );
8864 tellClients(kIOMessageSystemWillPowerOn);
8865 preventTransitionToUserActive(false);
8866 }
8867
8868 //******************************************************************************
8869 // fullWakeDelayedWork
8870 //
8871 // System has already entered full wake. Invoked by a delayed thread call.
8872 //******************************************************************************
8873
8874 void
8875 IOPMrootDomain::fullWakeDelayedWork( void )
8876 {
8877 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8878 if (!gIOPMWorkLoop->inGate()) {
8879 gIOPMWorkLoop->runAction(
8880 OSMemberFunctionCast(IOWorkLoop::Action, this,
8881 &IOPMrootDomain::fullWakeDelayedWork), this);
8882 return;
8883 }
8884
8885 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
8886 _currentCapability, _pendingCapability, _highestCapability,
8887 clamshellDisabled, clamshellSleepDisableMask);
8888
8889 if (clamshellExists &&
8890 CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
8891 !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
8892 if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
8893 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8894 } else {
8895 // Not the initial full wake after waking from sleep.
8896 // Evaluate the clamshell for rdar://problem/9157444.
8897 receivePowerNotification(kLocalEvalClamshellCommand);
8898 }
8899 }
8900 #endif
8901 }
8902
8903 //******************************************************************************
8904 // evaluateAssertions
8905 //
8906 //******************************************************************************
8907
8908 // Bitmask of all kernel assertions that prevent system idle sleep.
8909 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
8910 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
8911 (kIOPMDriverAssertionReservedBit7 | \
8912 kIOPMDriverAssertionPreventSystemIdleSleepBit)
8913
8914 void
8915 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
8916 {
8917 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
8918
8919 messageClients(kIOPMMessageDriverAssertionsChanged);
8920
8921 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
8922 if (wrangler) {
8923 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
8924
8925 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
8926 wrangler->setIgnoreIdleTimer( value );
8927 }
8928 }
8929
8930 if (changedBits & kIOPMDriverAssertionCPUBit) {
8931 if (_aotNow) {
8932 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
8933 }
8934 evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
8935 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
8936 AbsoluteTime now;
8937 clock_usec_t microsecs;
8938 clock_get_uptime(&now);
8939 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
8940 absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
8941 if (assertOnWakeReport) {
8942 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
8943 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
8944 }
8945 }
8946 }
8947
8948 if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
8949 if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
8950 if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
8951 DLOG("PreventIdleSleep driver assertion raised\n");
8952 bool ok = updatePreventIdleSleepList(this, true);
8953 if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
8954 // Cancel idle sleep if there is one in progress
8955 cancelIdlePowerDown(this);
8956 }
8957 }
8958 } else {
8959 DLOG("PreventIdleSleep driver assertion dropped\n");
8960 updatePreventIdleSleepList(this, false);
8961 }
8962 }
8963 }
8964
8965 // MARK: -
8966 // MARK: Statistics
8967
8968 //******************************************************************************
8969 // pmStats
8970 //
8971 //******************************************************************************
8972
8973 void
8974 IOPMrootDomain::pmStatsRecordEvent(
8975 int eventIndex,
8976 AbsoluteTime timestamp)
8977 {
8978 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
8979 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
8980 uint64_t delta;
8981 uint64_t nsec;
8982 OSSharedPtr<OSData> publishPMStats;
8983
8984 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
8985
8986 absolutetime_to_nanoseconds(timestamp, &nsec);
8987
8988 switch (eventIndex) {
8989 case kIOPMStatsHibernateImageWrite:
8990 if (starting) {
8991 gPMStats.hibWrite.start = nsec;
8992 } else if (stopping) {
8993 gPMStats.hibWrite.stop = nsec;
8994 }
8995
8996 if (stopping) {
8997 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
8998 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
8999 }
9000 break;
9001 case kIOPMStatsHibernateImageRead:
9002 if (starting) {
9003 gPMStats.hibRead.start = nsec;
9004 } else if (stopping) {
9005 gPMStats.hibRead.stop = nsec;
9006 }
9007
9008 if (stopping) {
9009 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9010 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9011
9012 publishPMStats = OSData::withBytes(&gPMStats, sizeof(gPMStats));
9013 setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9014 bzero(&gPMStats, sizeof(gPMStats));
9015 }
9016 break;
9017 }
9018 }
9019
9020 /*
9021 * Appends a record of the application response to
9022 * IOPMrootDomain::pmStatsAppResponses
9023 */
9024 void
9025 IOPMrootDomain::pmStatsRecordApplicationResponse(
9026 const OSSymbol *response,
9027 const char *name,
9028 int messageType,
9029 uint32_t delay_ms,
9030 uint64_t id,
9031 OSObject *object,
9032 IOPMPowerStateIndex powerState,
9033 bool async)
9034 {
9035 OSSharedPtr<OSDictionary> responseDescription;
9036 OSSharedPtr<OSNumber> delayNum;
9037 OSSharedPtr<OSNumber> powerCaps;
9038 OSSharedPtr<OSNumber> pidNum;
9039 OSSharedPtr<OSNumber> msgNum;
9040 OSSharedPtr<const OSSymbol> appname;
9041 OSSharedPtr<const OSSymbol> sleep;
9042 OSSharedPtr<const OSSymbol> wake;
9043 IOPMServiceInterestNotifier *notify = NULL;
9044
9045 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9046 if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9047 notify->ackTimeoutCnt++;
9048 } else {
9049 notify->ackTimeoutCnt = 0;
9050 }
9051 }
9052
9053 if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9054 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9055 return;
9056 }
9057
9058
9059 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9060 kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9061 } else if (notify) {
9062 // User space app or kernel capability client
9063 if (id) {
9064 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9065 } else {
9066 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9067 }
9068 notify->msgType = 0;
9069 }
9070
9071 responseDescription = OSDictionary::withCapacity(5);
9072 if (responseDescription) {
9073 if (response) {
9074 responseDescription->setObject(_statsResponseTypeKey.get(), response);
9075 }
9076
9077 msgNum = OSNumber::withNumber(messageType, 32);
9078 if (msgNum) {
9079 responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9080 }
9081
9082 if (!name && notify && notify->identifier) {
9083 name = notify->identifier->getCStringNoCopy();
9084 }
9085
9086 if (name && (strlen(name) > 0)) {
9087 appname = OSSymbol::withCString(name);
9088 if (appname) {
9089 responseDescription->setObject(_statsNameKey.get(), appname.get());
9090 }
9091 }
9092
9093 if (!id && notify) {
9094 id = notify->uuid0;
9095 }
9096 if (id != 0) {
9097 pidNum = OSNumber::withNumber(id, 64);
9098 if (pidNum) {
9099 responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9100 }
9101 }
9102
9103 delayNum = OSNumber::withNumber(delay_ms, 32);
9104 if (delayNum) {
9105 responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9106 }
9107
9108 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9109 powerCaps = OSNumber::withNumber(powerState, 32);
9110
9111 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9112 static const char * driverCallTypes[] = {
9113 [kDriverCallInformPreChange] = "powerStateWillChangeTo",
9114 [kDriverCallInformPostChange] = "powerStateDidChangeTo",
9115 [kDriverCallSetPowerState] = "setPowerState"
9116 };
9117
9118 if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9119 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9120 name, id, driverCallTypes[messageType], (uint32_t) powerState,
9121 async ? "async " : "", delay_ms);
9122 }
9123 #endif
9124 } else {
9125 powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9126 }
9127 if (powerCaps) {
9128 responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9129 }
9130
9131 sleep = OSSymbol::withCString("Sleep");
9132 wake = OSSymbol::withCString("Wake");
9133 if (_systemTransitionType == kSystemTransitionSleep) {
9134 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9135 } else if (_systemTransitionType == kSystemTransitionWake) {
9136 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9137 } else if (_systemTransitionType == kSystemTransitionCapability) {
9138 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9139 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9140 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9141 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9142 }
9143 }
9144
9145 IOLockLock(pmStatsLock);
9146 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9147 pmStatsAppResponses->setObject(responseDescription.get());
9148 }
9149 IOLockUnlock(pmStatsLock);
9150 }
9151
9152 return;
9153 }
9154
9155 // MARK: -
9156 // MARK: PMTraceWorker
9157
9158 //******************************************************************************
9159 // TracePoint support
9160 //
9161 //******************************************************************************
9162
9163 #define kIOPMRegisterNVRAMTracePointHandlerKey \
9164 "IOPMRegisterNVRAMTracePointHandler"
9165
9166 IOReturn
9167 IOPMrootDomain::callPlatformFunction(
9168 const OSSymbol * functionName,
9169 bool waitForFunction,
9170 void * param1, void * param2,
9171 void * param3, void * param4 )
9172 {
9173 if (pmTracer && functionName &&
9174 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9175 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9176 uint32_t tracePointPhases, tracePointPCI;
9177 uint64_t statusCode;
9178
9179 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9180 pmTracer->tracePointTarget = (void *) param2;
9181 tracePointPCI = (uint32_t)(uintptr_t) param3;
9182 tracePointPhases = (uint32_t)(uintptr_t) param4;
9183 if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9184 OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9185 if (node) {
9186 OSSharedPtr<OSObject> bootRomFailureProp;
9187 bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9188 OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9189 uint32_t bootFailureCode;
9190 if (data && data->getLength() == sizeof(bootFailureCode)) {
9191 // Failure code from EFI/BootRom is a four byte structure
9192 memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9193 tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9194 }
9195 }
9196 }
9197 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9198 if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9199 MSG("Sleep failure code 0x%08x 0x%08x\n",
9200 tracePointPCI, tracePointPhases);
9201 }
9202 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9203 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9204
9205 return kIOReturnSuccess;
9206 }
9207 #if HIBERNATION
9208 else if (functionName &&
9209 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9210 if (gSleepPolicyHandler) {
9211 return kIOReturnExclusiveAccess;
9212 }
9213 if (!param1) {
9214 return kIOReturnBadArgument;
9215 }
9216 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9217 gSleepPolicyTarget = (void *) param2;
9218 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9219 return kIOReturnSuccess;
9220 }
9221 #endif
9222
9223 return super::callPlatformFunction(
9224 functionName, waitForFunction, param1, param2, param3, param4);
9225 }
9226
9227 void
9228 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9229 uintptr_t param1, uintptr_t param2, uintptr_t param3)
9230 {
9231 uint32_t code = IODBG_POWER(event);
9232 uint64_t regId = id;
9233 if (regId == 0) {
9234 regId = getRegistryEntryID();
9235 }
9236 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9237 }
9238
9239 void
9240 IOPMrootDomain::tracePoint( uint8_t point )
9241 {
9242 if (systemBooting) {
9243 return;
9244 }
9245
9246 if (kIOPMTracePointWakeCapabilityClients == point) {
9247 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9248 }
9249
9250 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9251 pmTracer->tracePoint(point);
9252 }
9253
9254 static void
9255 kext_log_putc(char c)
9256 {
9257 if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9258 return;
9259 }
9260 if (c == '(' || c == '[' || c == ' ') {
9261 c = 0;
9262 gKextNameEnd = true;
9263 }
9264
9265 gKextNameBuf[gKextNamePos++] = c;
9266 }
9267
9268 static int
9269 kext_log(const char *fmt, ...)
9270 {
9271 va_list listp;
9272
9273 va_start(listp, fmt);
9274 _doprnt(fmt, &listp, &kext_log_putc, 16);
9275 va_end(listp);
9276
9277 return 0;
9278 }
9279
9280 static OSPtr<const OSSymbol>
9281 copyKextIdentifierWithAddress(vm_address_t address)
9282 {
9283 OSSharedPtr<const OSSymbol> identifer;
9284
9285 IOLockLock(gHaltLogLock);
9286
9287 gKextNameEnd = false;
9288 gKextNamePos = 0;
9289 gKextNameBuf[0] = 0;
9290
9291 OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9292 gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9293 identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9294
9295 IOLockUnlock(gHaltLogLock);
9296
9297 return identifer;
9298 }
9299
9300 // Caller serialized using PM workloop
9301 const char *
9302 IOPMrootDomain::getNotificationClientName(OSObject *object)
9303 {
9304 IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9305 const char *clientName = "UNKNOWN";
9306
9307 if (!notifier->clientName) {
9308 // Check for user client
9309 if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9310 OSNumber *clientID = NULL;
9311 messageClient(kIOMessageCopyClientID, object, &clientID);
9312 if (clientID) {
9313 OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9314 if (string) {
9315 notifier->clientName = OSSymbol::withString(string.get());
9316 }
9317 clientID->release();
9318 }
9319 } else if (notifier->identifier) {
9320 notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9321 }
9322 }
9323
9324 if (notifier->clientName) {
9325 clientName = notifier->clientName->getCStringNoCopy();
9326 }
9327
9328 return clientName;
9329 }
9330
9331 void
9332 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9333 {
9334 IOPMServiceInterestNotifier *notifier;
9335
9336 if (systemBooting) {
9337 return;
9338 }
9339 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9340 if (!notifier) {
9341 return;
9342 }
9343
9344 if (start) {
9345 pmTracer->traceDetail(notifier->uuid0 >> 32);
9346 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9347 (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9348
9349 // Update notifier state used for response/ack logging
9350 notifier->msgIndex = msgIndex;
9351 notifier->msgAbsTime = timestamp;
9352
9353 if (msgIndex != UINT_MAX) {
9354 DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9355 } else {
9356 DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9357 }
9358
9359 assert(notifierObject == NULL);
9360 notifierThread = current_thread();
9361 notifierObject.reset(notifier, OSRetain);
9362 } else {
9363 uint64_t nsec;
9364 uint32_t delayMS;
9365
9366 SUB_ABSOLUTETIME(&timestamp, &notifier->msgAbsTime);
9367 absolutetime_to_nanoseconds(timestamp, &nsec);
9368 delayMS = (uint32_t)(nsec / 1000000ULL);
9369 if (delayMS > notifier->maxMsgDelayMS) {
9370 notifier->maxMsgDelayMS = delayMS;
9371 }
9372
9373 assert(notifierObject == notifier);
9374 notifierObject.reset();
9375 notifierThread = NULL;
9376 }
9377 }
9378
9379 void
9380 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9381 {
9382 if (systemBooting) {
9383 return;
9384 }
9385 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9386 if (!notifier) {
9387 return;
9388 }
9389
9390 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9391 (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9392
9393 DLOG("%s[%u] ack from %s took %d ms\n",
9394 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9395 if (delay_ms > notifier->maxAckDelayMS) {
9396 notifier->maxAckDelayMS = delay_ms;
9397 }
9398 }
9399
9400 void
9401 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
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)(ack_time_us / 1000), (uintptr_t) delay_ms);
9413
9414 if (ack_time_us == 0) {
9415 // Client work is done and ack will not be forthcoming
9416 DLOG("%s[%u] response from %s took %d ms\n",
9417 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9418 } else {
9419 // Client needs more time and it must ack within ack_time_us
9420 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9421 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9422 }
9423 }
9424
9425 void
9426 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9427 {
9428 if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9429 return;
9430 }
9431 if (systemBooting) {
9432 return;
9433 }
9434 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9435 if (!notifier) {
9436 return;
9437 }
9438
9439 DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9440 }
9441
9442 void
9443 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9444 {
9445 if (!systemBooting) {
9446 uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
9447 pmTracer->traceDetail( detail );
9448 kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
9449 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
9450 }
9451 }
9452
9453 void
9454 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9455 {
9456 size_t reportSize;
9457 void **report = NULL;
9458 uint32_t bktCnt;
9459 uint32_t bktSize;
9460 uint32_t *clientCnt;
9461
9462 ASSERT_GATED();
9463
9464 report = NULL;
9465 if (channel_id == kAssertDelayChID) {
9466 report = &assertOnWakeReport;
9467 bktCnt = kAssertDelayBcktCnt;
9468 bktSize = kAssertDelayBcktSize;
9469 clientCnt = &assertOnWakeClientCnt;
9470 } else if (channel_id == kSleepDelaysChID) {
9471 report = &sleepDelaysReport;
9472 bktCnt = kSleepDelaysBcktCnt;
9473 bktSize = kSleepDelaysBcktSize;
9474 clientCnt = &sleepDelaysClientCnt;
9475 } else {
9476 assert(false);
9477 return;
9478 }
9479
9480 switch (action) {
9481 case kIOReportEnable:
9482
9483 if (*report) {
9484 (*clientCnt)++;
9485 break;
9486 }
9487
9488 reportSize = HISTREPORT_BUFSIZE(bktCnt);
9489 *report = IOMalloc(reportSize);
9490 if (*report == NULL) {
9491 break;
9492 }
9493 bzero(*report, reportSize);
9494 HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9495 getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9496
9497 if (channel_id == kAssertDelayChID) {
9498 assertOnWakeSecs = 0;
9499 }
9500
9501 break;
9502
9503 case kIOReportDisable:
9504 if (*clientCnt == 0) {
9505 break;
9506 }
9507 if (*clientCnt == 1) {
9508 IOFree(*report, HISTREPORT_BUFSIZE(bktCnt));
9509 *report = NULL;
9510 }
9511 (*clientCnt)--;
9512
9513 if (channel_id == kAssertDelayChID) {
9514 assertOnWakeSecs = -1; // Invalid value to prevent updates
9515 }
9516 break;
9517
9518 case kIOReportGetDimensions:
9519 if (*report) {
9520 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9521 }
9522 break;
9523 }
9524
9525 return;
9526 }
9527
9528 IOReturn
9529 IOPMrootDomain::configureReport(IOReportChannelList *channelList,
9530 IOReportConfigureAction action,
9531 void *result,
9532 void *destination)
9533 {
9534 unsigned cnt;
9535 uint64_t configAction = (uint64_t)action;
9536
9537 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9538 if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
9539 (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
9540 (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
9541 if (action != kIOReportGetDimensions) {
9542 continue;
9543 }
9544 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
9545 } else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
9546 (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
9547 gIOPMWorkLoop->runAction(
9548 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
9549 (OSObject *)this, (void *)channelList->channels[cnt].channel_id,
9550 (void *)configAction, (void *)result);
9551 }
9552 }
9553
9554 return super::configureReport(channelList, action, result, destination);
9555 }
9556
9557 IOReturn
9558 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9559 {
9560 uint32_t size2cpy;
9561 void *data2cpy;
9562 void **report;
9563
9564 ASSERT_GATED();
9565
9566 report = NULL;
9567 if (ch_id == kAssertDelayChID) {
9568 report = &assertOnWakeReport;
9569 } else if (ch_id == kSleepDelaysChID) {
9570 report = &sleepDelaysReport;
9571 } else {
9572 assert(false);
9573 return kIOReturnBadArgument;
9574 }
9575
9576 if (*report == NULL) {
9577 return kIOReturnNotOpen;
9578 }
9579
9580 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9581 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9582 return kIOReturnOverrun;
9583 }
9584
9585 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9586 dest->appendBytes(data2cpy, size2cpy);
9587
9588 return kIOReturnSuccess;
9589 }
9590
9591 IOReturn
9592 IOPMrootDomain::updateReport(IOReportChannelList *channelList,
9593 IOReportUpdateAction action,
9594 void *result,
9595 void *destination)
9596 {
9597 uint32_t size2cpy;
9598 void *data2cpy;
9599 uint8_t buf[SIMPLEREPORT_BUFSIZE];
9600 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9601 unsigned cnt;
9602 uint64_t ch_id;
9603
9604 if (action != kIOReportCopyChannelData) {
9605 goto exit;
9606 }
9607
9608 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9609 ch_id = channelList->channels[cnt].channel_id;
9610
9611 if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
9612 gIOPMWorkLoop->runAction(
9613 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
9614 (OSObject *)this, (void *)ch_id,
9615 (void *)result, (void *)dest);
9616 continue;
9617 } else if ((ch_id == kSleepCntChID) ||
9618 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9619 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9620 } else {
9621 continue;
9622 }
9623
9624 if (ch_id == kSleepCntChID) {
9625 SIMPLEREPORT_SETVALUE(buf, sleepCnt);
9626 } else if (ch_id == kDarkWkCntChID) {
9627 SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
9628 } else if (ch_id == kUserWkCntChID) {
9629 SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
9630 }
9631
9632 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9633 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9634 dest->appendBytes(data2cpy, size2cpy);
9635 }
9636
9637 exit:
9638 return super::updateReport(channelList, action, result, destination);
9639 }
9640
9641
9642 //******************************************************************************
9643 // PMTraceWorker Class
9644 //
9645 //******************************************************************************
9646
9647 #undef super
9648 #define super OSObject
9649 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9650
9651 #define kPMBestGuessPCIDevicesCount 25
9652 #define kPMMaxRTCBitfieldSize 32
9653
9654 OSPtr<PMTraceWorker>
9655 PMTraceWorker::tracer(IOPMrootDomain * owner)
9656 {
9657 OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9658 if (!me || !me->init()) {
9659 return NULL;
9660 }
9661
9662 DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9663
9664 // Note that we cannot instantiate the PCI device -> bit mappings here, since
9665 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
9666 // this dictionary lazily.
9667 me->owner = owner;
9668 me->pciDeviceBitMappings = NULL;
9669 me->pmTraceWorkerLock = IOLockAlloc();
9670 me->tracePhase = kIOPMTracePointSystemUp;
9671 me->traceData32 = 0;
9672 me->loginWindowData = 0;
9673 me->coreDisplayData = 0;
9674 me->coreGraphicsData = 0;
9675 return me;
9676 }
9677
9678 void
9679 PMTraceWorker::RTC_TRACE(void)
9680 {
9681 if (tracePointHandler && tracePointTarget) {
9682 uint32_t wordA;
9683
9684 IOLockLock(pmTraceWorkerLock);
9685 wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9686 (coreGraphicsData << 8) | tracePhase;
9687 IOLockUnlock(pmTraceWorkerLock);
9688
9689 tracePointHandler( tracePointTarget, traceData32, wordA );
9690 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
9691 }
9692 #if DEVELOPMENT || DEBUG
9693 if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
9694 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
9695 IOLock *l = IOLockAlloc();
9696 IOLockLock(l);
9697 IOLockLock(l);
9698 }
9699 #endif
9700 }
9701
9702 int
9703 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
9704 {
9705 OSSharedPtr<const OSSymbol> deviceName;
9706 int index = -1;
9707
9708 IOLockLock(pmTraceWorkerLock);
9709
9710 if (!pciDeviceBitMappings) {
9711 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
9712 if (!pciDeviceBitMappings) {
9713 goto exit;
9714 }
9715 }
9716
9717 // Check for bitmask overflow.
9718 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
9719 goto exit;
9720 }
9721
9722 if ((deviceName = pciDevice->copyName()) &&
9723 (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
9724 pciDeviceBitMappings->setObject(deviceName.get())) {
9725 index = pciDeviceBitMappings->getCount() - 1;
9726 _LOG("PMTrace PCI array: set object %s => %d\n",
9727 deviceName->getCStringNoCopy(), index);
9728 }
9729
9730 if (!addedToRegistry && (index >= 0)) {
9731 addedToRegistry = owner->setProperty("PCITopLevel", this);
9732 }
9733
9734 exit:
9735 IOLockUnlock(pmTraceWorkerLock);
9736 return index;
9737 }
9738
9739 bool
9740 PMTraceWorker::serialize(OSSerialize *s) const
9741 {
9742 bool ok = false;
9743 if (pciDeviceBitMappings) {
9744 IOLockLock(pmTraceWorkerLock);
9745 ok = pciDeviceBitMappings->serialize(s);
9746 IOLockUnlock(pmTraceWorkerLock);
9747 }
9748 return ok;
9749 }
9750
9751 void
9752 PMTraceWorker::tracePoint(uint8_t phase)
9753 {
9754 // clear trace detail when phase begins
9755 if (tracePhase != phase) {
9756 traceData32 = 0;
9757 }
9758
9759 tracePhase = phase;
9760
9761 DLOG("trace point 0x%02x\n", tracePhase);
9762 RTC_TRACE();
9763 }
9764
9765 void
9766 PMTraceWorker::traceDetail(uint32_t detail)
9767 {
9768 if (detail == traceData32) {
9769 return;
9770 }
9771 traceData32 = detail;
9772 RTC_TRACE();
9773 }
9774
9775 void
9776 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
9777 {
9778 switch (component) {
9779 case kIOPMLoginWindowProgress:
9780 loginWindowData = data & kIOPMLoginWindowProgressMask;
9781 break;
9782 case kIOPMCoreDisplayProgress:
9783 coreDisplayData = data & kIOPMCoreDisplayProgressMask;
9784 break;
9785 case kIOPMCoreGraphicsProgress:
9786 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
9787 break;
9788 default:
9789 return;
9790 }
9791
9792 DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
9793 RTC_TRACE();
9794 }
9795
9796 void
9797 PMTraceWorker::tracePCIPowerChange(
9798 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
9799 {
9800 uint32_t bitMask;
9801 uint32_t expectedFlag;
9802
9803 // Ignore PCI changes outside of system sleep/wake.
9804 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
9805 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
9806 return;
9807 }
9808
9809 // Only record the WillChange transition when going to sleep,
9810 // and the DidChange on the way up.
9811 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
9812 expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
9813 kIOPMDomainWillChange : kIOPMDomainDidChange;
9814 if (changeFlags != expectedFlag) {
9815 return;
9816 }
9817
9818 // Mark this device off in our bitfield
9819 if (bitNum < kPMMaxRTCBitfieldSize) {
9820 bitMask = (1 << bitNum);
9821
9822 if (kPowerChangeStart == type) {
9823 traceData32 |= bitMask;
9824 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
9825 service->getName(), bitNum, bitMask, traceData32);
9826 owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
9827 } else {
9828 traceData32 &= ~bitMask;
9829 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
9830 service->getName(), bitNum, bitMask, traceData32);
9831 owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
9832 }
9833
9834 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
9835 RTC_TRACE();
9836 }
9837 }
9838
9839 uint64_t
9840 PMTraceWorker::getPMStatusCode()
9841 {
9842 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
9843 }
9844
9845 uint8_t
9846 PMTraceWorker::getTracePhase()
9847 {
9848 return tracePhase;
9849 }
9850
9851 uint32_t
9852 PMTraceWorker::getTraceData()
9853 {
9854 return traceData32;
9855 }
9856
9857 // MARK: -
9858 // MARK: PMHaltWorker
9859
9860 //******************************************************************************
9861 // PMHaltWorker Class
9862 //
9863 //******************************************************************************
9864
9865 PMHaltWorker *
9866 PMHaltWorker::worker( void )
9867 {
9868 PMHaltWorker * me;
9869 IOThread thread;
9870
9871 do {
9872 me = OSTypeAlloc( PMHaltWorker );
9873 if (!me || !me->init()) {
9874 break;
9875 }
9876
9877 me->lock = IOLockAlloc();
9878 if (!me->lock) {
9879 break;
9880 }
9881
9882 DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
9883 me->retain(); // thread holds extra retain
9884 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
9885 me->release();
9886 break;
9887 }
9888 thread_deallocate(thread);
9889 return me;
9890 } while (false);
9891
9892 if (me) {
9893 me->release();
9894 }
9895 return NULL;
9896 }
9897
9898 void
9899 PMHaltWorker::free( void )
9900 {
9901 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
9902 if (lock) {
9903 IOLockFree(lock);
9904 lock = NULL;
9905 }
9906 return OSObject::free();
9907 }
9908
9909 void
9910 PMHaltWorker::main( void * arg, wait_result_t waitResult )
9911 {
9912 PMHaltWorker * me = (PMHaltWorker *) arg;
9913
9914 IOLockLock( gPMHaltLock );
9915 gPMHaltBusyCount++;
9916 me->depth = gPMHaltDepth;
9917 IOLockUnlock( gPMHaltLock );
9918
9919 while (me->depth >= 0) {
9920 PMHaltWorker::work( me );
9921
9922 IOLockLock( gPMHaltLock );
9923 if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
9924 // This is the last thread to finish work on this level,
9925 // inform everyone to start working on next lower level.
9926 gPMHaltDepth--;
9927 me->depth = gPMHaltDepth;
9928 gPMHaltIdleCount = 0;
9929 thread_wakeup((event_t) &gPMHaltIdleCount);
9930 } else {
9931 // One or more threads are still working on this level,
9932 // this thread must wait.
9933 me->depth = gPMHaltDepth - 1;
9934 do {
9935 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
9936 } while (me->depth != gPMHaltDepth);
9937 }
9938 IOLockUnlock( gPMHaltLock );
9939 }
9940
9941 // No more work to do, terminate thread
9942 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
9943 thread_wakeup( &gPMHaltDepth );
9944 me->release();
9945 }
9946
9947 void
9948 PMHaltWorker::work( PMHaltWorker * me )
9949 {
9950 OSSharedPtr<IOService> service;
9951 OSSet * inner;
9952 AbsoluteTime startTime, elapsedTime;
9953 UInt32 deltaTime;
9954 bool timeout;
9955
9956 while (true) {
9957 timeout = false;
9958
9959 // Claim an unit of work from the shared pool
9960 IOLockLock( gPMHaltLock );
9961 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
9962 if (inner) {
9963 service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
9964 if (service) {
9965 inner->removeObject(service.get());
9966 }
9967 }
9968 IOLockUnlock( gPMHaltLock );
9969 if (!service) {
9970 break; // no more work at this depth
9971 }
9972 clock_get_uptime(&startTime);
9973
9974 if (!service->isInactive() &&
9975 service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
9976 IOLockLock(me->lock);
9977 me->startTime = startTime;
9978 me->service = service.get();
9979 me->timeout = false;
9980 IOLockUnlock(me->lock);
9981
9982 service->systemWillShutdown( gPMHaltMessageType);
9983
9984 // Wait for driver acknowledgement
9985 IOLockLock(me->lock);
9986 while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
9987 IOLockSleep(me->lock, me, THREAD_UNINT);
9988 }
9989 me->service = NULL;
9990 timeout = me->timeout;
9991 IOLockUnlock(me->lock);
9992 }
9993
9994 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
9995 if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
9996 LOG("%s driver %s (0x%llx) took %u ms\n",
9997 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
9998 "PowerOff" : "Restart",
9999 service->getName(), service->getRegistryEntryID(),
10000 (uint32_t) deltaTime );
10001 halt_log_enter("PowerOff/Restart handler completed",
10002 OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10003 elapsedTime);
10004 }
10005
10006 me->visits++;
10007 }
10008 }
10009
10010 void
10011 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10012 {
10013 UInt64 nano;
10014 AbsoluteTime startTime;
10015 AbsoluteTime endTime;
10016
10017 endTime = *now;
10018
10019 IOLockLock(me->lock);
10020 if (me->service && !me->timeout) {
10021 startTime = me->startTime;
10022 nano = 0;
10023 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10024 SUB_ABSOLUTETIME(&endTime, &startTime);
10025 absolutetime_to_nanoseconds(endTime, &nano);
10026 }
10027 if (nano > 3000000000ULL) {
10028 me->timeout = true;
10029
10030 halt_log_enter("PowerOff/Restart still waiting on handler",
10031 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10032 endTime);
10033 MSG("%s still waiting on %s\n",
10034 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart",
10035 me->service->getName());
10036 }
10037 }
10038 IOLockUnlock(me->lock);
10039 }
10040
10041 //******************************************************************************
10042 // acknowledgeSystemWillShutdown
10043 //
10044 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10045 //******************************************************************************
10046
10047 void
10048 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10049 {
10050 PMHaltWorker * worker;
10051 OSSharedPtr<OSObject> prop;
10052
10053 if (!from) {
10054 return;
10055 }
10056
10057 //DLOG("%s acknowledged\n", from->getName());
10058 prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10059 if (prop) {
10060 worker = (PMHaltWorker *) prop.get();
10061 IOLockLock(worker->lock);
10062 from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10063 thread_wakeup((event_t) worker);
10064 IOLockUnlock(worker->lock);
10065 } else {
10066 DLOG("%s acknowledged without worker property\n",
10067 from->getName());
10068 }
10069 }
10070
10071
10072 //******************************************************************************
10073 // notifySystemShutdown
10074 //
10075 // Notify all objects in PM tree that system will shutdown or restart
10076 //******************************************************************************
10077
10078 static void
10079 notifySystemShutdown( IOService * root, uint32_t messageType )
10080 {
10081 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10082 OSSharedPtr<IORegistryIterator> iter;
10083 IORegistryEntry * entry;
10084 IOService * node;
10085 OSSet * inner;
10086 OSSharedPtr<OSSet> newInner;
10087 PMHaltWorker * workers[kPMHaltMaxWorkers];
10088 AbsoluteTime deadline;
10089 unsigned int totalNodes = 0;
10090 unsigned int depth;
10091 unsigned int rootDepth;
10092 unsigned int numWorkers;
10093 unsigned int count;
10094 int waitResult;
10095 void * baseFunc;
10096 bool ok;
10097
10098 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10099
10100 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10101
10102 // Iterate the entire PM tree starting from root
10103
10104 rootDepth = root->getDepth( gIOPowerPlane );
10105 if (!rootDepth) {
10106 goto done;
10107 }
10108
10109 // debug - for repeated test runs
10110 while (PMHaltWorker::metaClass->getInstanceCount()) {
10111 IOSleep(1);
10112 }
10113
10114 if (!gPMHaltArray) {
10115 gPMHaltArray = OSArray::withCapacity(40);
10116 if (!gPMHaltArray) {
10117 goto done;
10118 }
10119 } else { // debug
10120 gPMHaltArray->flushCollection();
10121 }
10122
10123 if (!gPMHaltLock) {
10124 gPMHaltLock = IOLockAlloc();
10125 if (!gPMHaltLock) {
10126 goto done;
10127 }
10128 }
10129
10130 if (!gPMHaltClientAcknowledgeKey) {
10131 gPMHaltClientAcknowledgeKey =
10132 OSSymbol::withCStringNoCopy("PMShutdown");
10133 if (!gPMHaltClientAcknowledgeKey) {
10134 goto done;
10135 }
10136 }
10137
10138 gPMHaltMessageType = messageType;
10139
10140 // Depth-first walk of PM plane
10141
10142 iter = IORegistryIterator::iterateOver(
10143 root, gIOPowerPlane, kIORegistryIterateRecursively);
10144
10145 if (iter) {
10146 while ((entry = iter->getNextObject())) {
10147 node = OSDynamicCast(IOService, entry);
10148 if (!node) {
10149 continue;
10150 }
10151
10152 if (baseFunc ==
10153 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10154 continue;
10155 }
10156
10157 depth = node->getDepth( gIOPowerPlane );
10158 if (depth <= rootDepth) {
10159 continue;
10160 }
10161
10162 ok = false;
10163
10164 // adjust to zero based depth
10165 depth -= (rootDepth + 1);
10166
10167 // gPMHaltArray is an array of containers, each container
10168 // refers to nodes with the same depth.
10169
10170 count = gPMHaltArray->getCount();
10171 while (depth >= count) {
10172 // expand array and insert placeholders
10173 gPMHaltArray->setObject(PLACEHOLDER);
10174 count++;
10175 }
10176 count = gPMHaltArray->getCount();
10177 if (depth < count) {
10178 inner = (OSSet *)gPMHaltArray->getObject(depth);
10179 if (inner == PLACEHOLDER) {
10180 newInner = OSSet::withCapacity(40);
10181 if (newInner) {
10182 gPMHaltArray->replaceObject(depth, newInner.get());
10183 inner = newInner.get();
10184 }
10185 }
10186
10187 // PM nodes that appear more than once in the tree will have
10188 // the same depth, OSSet will refuse to add the node twice.
10189 if (inner) {
10190 ok = inner->setObject(node);
10191 }
10192 }
10193 if (!ok) {
10194 DLOG("Skipped PM node %s\n", node->getName());
10195 }
10196 }
10197 }
10198
10199 // debug only
10200 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10201 count = 0;
10202 if (inner != PLACEHOLDER) {
10203 count = inner->getCount();
10204 }
10205 DLOG("Nodes at depth %u = %u\n", i, count);
10206 }
10207
10208 // strip placeholders (not all depths are populated)
10209 numWorkers = 0;
10210 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10211 if (inner == PLACEHOLDER) {
10212 gPMHaltArray->removeObject(i);
10213 continue;
10214 }
10215 count = inner->getCount();
10216 if (count > numWorkers) {
10217 numWorkers = count;
10218 }
10219 totalNodes += count;
10220 i++;
10221 }
10222
10223 if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10224 goto done;
10225 }
10226
10227 gPMHaltBusyCount = 0;
10228 gPMHaltIdleCount = 0;
10229 gPMHaltDepth = gPMHaltArray->getCount() - 1;
10230
10231 // Create multiple workers (and threads)
10232
10233 if (numWorkers > kPMHaltMaxWorkers) {
10234 numWorkers = kPMHaltMaxWorkers;
10235 }
10236
10237 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10238 totalNodes, gPMHaltArray->getCount(), numWorkers);
10239
10240 for (unsigned int i = 0; i < numWorkers; i++) {
10241 workers[i] = PMHaltWorker::worker();
10242 }
10243
10244 // Wait for workers to exhaust all available work
10245
10246 IOLockLock(gPMHaltLock);
10247 while (gPMHaltDepth >= 0) {
10248 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10249
10250 waitResult = IOLockSleepDeadline(
10251 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10252 if (THREAD_TIMED_OUT == waitResult) {
10253 AbsoluteTime now;
10254 clock_get_uptime(&now);
10255
10256 IOLockUnlock(gPMHaltLock);
10257 for (unsigned int i = 0; i < numWorkers; i++) {
10258 if (workers[i]) {
10259 PMHaltWorker::checkTimeout(workers[i], &now);
10260 }
10261 }
10262 IOLockLock(gPMHaltLock);
10263 }
10264 }
10265 IOLockUnlock(gPMHaltLock);
10266
10267 // Release all workers
10268
10269 for (unsigned int i = 0; i < numWorkers; i++) {
10270 if (workers[i]) {
10271 workers[i]->release();
10272 }
10273 // worker also retained by it's own thread
10274 }
10275
10276 done:
10277 DLOG("%s done\n", __FUNCTION__);
10278 return;
10279 }
10280
10281 // MARK: -
10282 // MARK: Kernel Assertion
10283
10284 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10285
10286 IOPMDriverAssertionID
10287 IOPMrootDomain::createPMAssertion(
10288 IOPMDriverAssertionType whichAssertionBits,
10289 IOPMDriverAssertionLevel assertionLevel,
10290 IOService *ownerService,
10291 const char *ownerDescription)
10292 {
10293 IOReturn ret;
10294 IOPMDriverAssertionID newAssertion;
10295
10296 if (!pmAssertions) {
10297 return 0;
10298 }
10299
10300 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10301
10302 if (kIOReturnSuccess == ret) {
10303 return newAssertion;
10304 } else {
10305 return 0;
10306 }
10307 }
10308
10309 IOReturn
10310 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10311 {
10312 if (!pmAssertions) {
10313 return kIOReturnInternalError;
10314 }
10315
10316 return pmAssertions->releaseAssertion(releaseAssertion);
10317 }
10318
10319
10320 IOReturn
10321 IOPMrootDomain::setPMAssertionLevel(
10322 IOPMDriverAssertionID assertionID,
10323 IOPMDriverAssertionLevel assertionLevel)
10324 {
10325 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10326 }
10327
10328 IOPMDriverAssertionLevel
10329 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10330 {
10331 IOPMDriverAssertionType sysLevels;
10332
10333 if (!pmAssertions || whichAssertion == 0) {
10334 return kIOPMDriverAssertionLevelOff;
10335 }
10336
10337 sysLevels = pmAssertions->getActivatedAssertions();
10338
10339 // Check that every bit set in argument 'whichAssertion' is asserted
10340 // in the aggregate bits.
10341 if ((sysLevels & whichAssertion) == whichAssertion) {
10342 return kIOPMDriverAssertionLevelOn;
10343 } else {
10344 return kIOPMDriverAssertionLevelOff;
10345 }
10346 }
10347
10348 IOReturn
10349 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10350 {
10351 if (!pmAssertions) {
10352 return kIOReturnNotFound;
10353 }
10354
10355 return pmAssertions->setUserAssertionLevels(inLevels);
10356 }
10357
10358 bool
10359 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10360 {
10361 if (pmAssertions) {
10362 pmAssertions->publishProperties();
10363 }
10364 return IOService::serializeProperties(s);
10365 }
10366
10367 OSSharedPtr<OSObject>
10368 IOPMrootDomain::copyProperty( const char * aKey) const
10369 {
10370 OSSharedPtr<OSObject> obj;
10371 obj = IOService::copyProperty(aKey);
10372
10373 if (obj) {
10374 return obj;
10375 }
10376
10377 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10378 sizeof(kIOPMSleepWakeWdogRebootKey))) {
10379 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10380 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10381 } else {
10382 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10383 }
10384 }
10385
10386 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10387 sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10388 if (swd_flags & SWD_VALID_LOGS) {
10389 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10390 } else {
10391 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10392 }
10393 }
10394
10395 /*
10396 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
10397 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10398 * issued by DisplayWrangler on darkwake.
10399 */
10400 if (!strcmp(aKey, "DesktopMode")) {
10401 if (desktopMode) {
10402 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10403 } else {
10404 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10405 }
10406 }
10407 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10408 if (displayIdleForDemandSleep) {
10409 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10410 } else {
10411 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10412 }
10413 }
10414
10415 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10416 OSSharedPtr<OSArray> array;
10417 WAKEEVENT_LOCK();
10418 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10419 OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10420 if (collection) {
10421 array = OSDynamicPtrCast<OSArray>(collection);
10422 }
10423 }
10424 WAKEEVENT_UNLOCK();
10425 return os::move(array);
10426 }
10427
10428 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10429 OSSharedPtr<OSArray> array;
10430 IOLockLock(pmStatsLock);
10431 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10432 OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10433 if (collection) {
10434 array = OSDynamicPtrCast<OSArray>(collection);
10435 }
10436 }
10437 IOLockUnlock(pmStatsLock);
10438 return os::move(array);
10439 }
10440
10441 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10442 OSArray *idleSleepList = NULL;
10443 gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10444 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10445 }
10446
10447 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10448 OSArray *systemSleepList = NULL;
10449 gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10450 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10451 }
10452
10453 if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10454 OSArray *idleSleepList = NULL;
10455 gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10456 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10457 }
10458
10459 if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10460 OSArray *systemSleepList = NULL;
10461 gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10462 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10463 }
10464 return NULL;
10465 }
10466
10467 // MARK: -
10468 // MARK: Wake Event Reporting
10469
10470 void
10471 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10472 {
10473 WAKEEVENT_LOCK();
10474 strlcpy(outBuf, gWakeReasonString, bufSize);
10475 WAKEEVENT_UNLOCK();
10476 }
10477
10478 void
10479 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10480 {
10481 WAKEEVENT_LOCK();
10482 strlcpy(outBuf, gShutdownReasonString, bufSize);
10483 WAKEEVENT_UNLOCK();
10484 }
10485
10486 //******************************************************************************
10487 // acceptSystemWakeEvents
10488 //
10489 // Private control for the acceptance of driver wake event claims.
10490 //******************************************************************************
10491
10492 void
10493 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10494 {
10495 bool logWakeReason = false;
10496
10497 WAKEEVENT_LOCK();
10498 switch (control) {
10499 case kAcceptSystemWakeEvents_Enable:
10500 assert(_acceptSystemWakeEvents == false);
10501 if (!_systemWakeEventsArray) {
10502 _systemWakeEventsArray = OSArray::withCapacity(4);
10503 }
10504 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10505 if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10506 gWakeReasonString[0] = '\0';
10507 if (_systemWakeEventsArray) {
10508 _systemWakeEventsArray->flushCollection();
10509 }
10510 }
10511
10512 // Remove stale WakeType property before system sleep
10513 removeProperty(kIOPMRootDomainWakeTypeKey);
10514 removeProperty(kIOPMRootDomainWakeReasonKey);
10515 break;
10516
10517 case kAcceptSystemWakeEvents_Disable:
10518 _acceptSystemWakeEvents = false;
10519 #if defined(XNU_TARGET_OS_OSX)
10520 logWakeReason = (gWakeReasonString[0] != '\0');
10521 #else /* !defined(XNU_TARGET_OS_OSX) */
10522 logWakeReason = gWakeReasonSysctlRegistered;
10523 #if DEVELOPMENT
10524 static int panic_allowed = -1;
10525
10526 if ((panic_allowed == -1) &&
10527 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10528 panic_allowed = 0;
10529 }
10530
10531 if (panic_allowed) {
10532 size_t i = 0;
10533 // Panic if wake reason is null or empty
10534 for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10535 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10536 break;
10537 }
10538 }
10539 if (i >= strlen(gWakeReasonString)) {
10540 panic("Wake reason is empty\n");
10541 }
10542 }
10543 #endif /* DEVELOPMENT */
10544 #endif /* !defined(XNU_TARGET_OS_OSX) */
10545
10546 // publish kIOPMRootDomainWakeReasonKey if not already set
10547 if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10548 setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10549 }
10550 break;
10551
10552 case kAcceptSystemWakeEvents_Reenable:
10553 assert(_acceptSystemWakeEvents == false);
10554 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10555 removeProperty(kIOPMRootDomainWakeReasonKey);
10556 break;
10557 }
10558 WAKEEVENT_UNLOCK();
10559
10560 if (logWakeReason) {
10561 MSG("system wake events: %s\n", gWakeReasonString);
10562 }
10563 }
10564
10565 //******************************************************************************
10566 // claimSystemWakeEvent
10567 //
10568 // For a driver to claim a device is the source/conduit of a system wake event.
10569 //******************************************************************************
10570
10571 void
10572 IOPMrootDomain::claimSystemWakeEvent(
10573 IOService * device,
10574 IOOptionBits flags,
10575 const char * reason,
10576 OSObject * details )
10577 {
10578 OSSharedPtr<const OSSymbol> deviceName;
10579 OSSharedPtr<OSNumber> deviceRegId;
10580 OSSharedPtr<OSNumber> claimTime;
10581 OSSharedPtr<OSData> flagsData;
10582 OSSharedPtr<OSString> reasonString;
10583 OSSharedPtr<OSDictionary> dict;
10584 uint64_t timestamp;
10585 bool addWakeReason;
10586
10587 if (!device || !reason) {
10588 return;
10589 }
10590
10591 pmEventTimeStamp(&timestamp);
10592
10593 IOOptionBits aotFlags = 0;
10594 bool needAOTEvaluate = FALSE;
10595
10596 if (kIOPMAOTModeAddEventFlags & _aotMode) {
10597 if (!strcmp("hold", reason)
10598 || !strcmp("help", reason)
10599 || !strcmp("menu", reason)
10600 || !strcmp("stockholm", reason)
10601 || !strcmp("ringer", reason)
10602 || !strcmp("ringerab", reason)
10603 || !strcmp("smc0", reason)
10604 || !strcmp("AOP.RTPWakeupAP", reason)
10605 || !strcmp("BT.OutboxNotEmpty", reason)
10606 || !strcmp("WL.OutboxNotEmpty", reason)) {
10607 flags |= kIOPMWakeEventAOTExit;
10608 }
10609 }
10610
10611 #if DEVELOPMENT || DEBUG
10612 if (_aotLingerTime && !strcmp("rtc", reason)) {
10613 flags |= kIOPMWakeEventAOTPossibleExit;
10614 }
10615 #endif /* DEVELOPMENT || DEBUG */
10616
10617 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10618 // Publishing the WakeType is serialized by the PM work loop
10619 if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
10620 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10621 (void *) _nextScheduledAlarmType.get());
10622 }
10623
10624 // Workaround for the missing wake HID event
10625 if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
10626 if (!strcmp("trackpadkeyboard", reason)) {
10627 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10628 (void *) gIOPMWakeTypeUserKey.get());
10629 }
10630 }
10631 #endif
10632
10633 deviceName = device->copyName(gIOServicePlane);
10634 deviceRegId = OSNumber::withNumber(device->getRegistryEntryID(), 64);
10635 claimTime = OSNumber::withNumber(timestamp, 64);
10636 flagsData = OSData::withBytes(&flags, sizeof(flags));
10637 reasonString = OSString::withCString(reason);
10638 dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
10639 if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
10640 goto done;
10641 }
10642
10643 dict->setObject(gIONameKey, deviceName.get());
10644 dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
10645 dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
10646 dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
10647 dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
10648 if (details) {
10649 dict->setObject(kIOPMWakeEventDetailsKey, details);
10650 }
10651
10652 WAKEEVENT_LOCK();
10653 addWakeReason = _acceptSystemWakeEvents;
10654 if (_aotMode) {
10655 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
10656 }
10657 aotFlags = (kIOPMWakeEventAOTFlags & flags);
10658 aotFlags = (aotFlags & ~_aotPendingFlags);
10659 needAOTEvaluate = false;
10660 if (_aotNow && aotFlags) {
10661 if (kIOPMWakeEventAOTPossibleExit & flags) {
10662 _aotMetrics->possibleCount++;
10663 }
10664 if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
10665 _aotMetrics->confirmedPossibleCount++;
10666 }
10667 if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
10668 _aotMetrics->rejectedPossibleCount++;
10669 }
10670 if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
10671 _aotMetrics->expiredPossibleCount++;
10672 }
10673
10674 _aotPendingFlags |= aotFlags;
10675 addWakeReason = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
10676 needAOTEvaluate = _aotReadyToFullWake;
10677 }
10678 DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
10679 reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
10680 _aotNow, pmTracer->getTracePhase(), addWakeReason);
10681
10682 if (!gWakeReasonSysctlRegistered) {
10683 // Lazy registration until the platform driver stops registering
10684 // the same name.
10685 gWakeReasonSysctlRegistered = true;
10686 #if !defined(XNU_TARGET_OS_OSX)
10687 sysctl_register_oid(&sysctl__kern_wakereason);
10688 #endif /* !defined(XNU_TARGET_OS_OSX) */
10689 }
10690 if (addWakeReason) {
10691 _systemWakeEventsArray->setObject(dict.get());
10692 if (gWakeReasonString[0] != '\0') {
10693 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
10694 }
10695 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
10696 }
10697
10698 WAKEEVENT_UNLOCK();
10699 if (needAOTEvaluate) {
10700 // Call aotEvaluate() on PM work loop since it may call
10701 // aotExit() which accesses PM state.
10702 pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
10703 }
10704
10705 done:
10706 return;
10707 }
10708
10709 //******************************************************************************
10710 // claimSystemBootEvent
10711 //
10712 // For a driver to claim a device is the source/conduit of a system boot event.
10713 //******************************************************************************
10714
10715 void
10716 IOPMrootDomain::claimSystemBootEvent(
10717 IOService * device,
10718 IOOptionBits flags,
10719 const char * reason,
10720 __unused OSObject * details )
10721 {
10722 if (!device || !reason) {
10723 return;
10724 }
10725
10726 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
10727 WAKEEVENT_LOCK();
10728 if (!gBootReasonSysctlRegistered) {
10729 // Lazy sysctl registration after setting gBootReasonString
10730 strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
10731 sysctl_register_oid(&sysctl__kern_bootreason);
10732 gBootReasonSysctlRegistered = true;
10733 }
10734 WAKEEVENT_UNLOCK();
10735 }
10736
10737 //******************************************************************************
10738 // claimSystemShutdownEvent
10739 //
10740 // For drivers to claim a system shutdown event on the ensuing boot.
10741 //******************************************************************************
10742
10743 void
10744 IOPMrootDomain::claimSystemShutdownEvent(
10745 IOService * device,
10746 IOOptionBits flags,
10747 const char * reason,
10748 __unused OSObject * details )
10749 {
10750 if (!device || !reason) {
10751 return;
10752 }
10753
10754 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
10755 WAKEEVENT_LOCK();
10756 if (gShutdownReasonString[0] != '\0') {
10757 strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
10758 }
10759 strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
10760
10761 if (!gShutdownReasonSysctlRegistered) {
10762 sysctl_register_oid(&sysctl__kern_shutdownreason);
10763 gShutdownReasonSysctlRegistered = true;
10764 }
10765 WAKEEVENT_UNLOCK();
10766 }
10767
10768 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10769
10770 // MARK: -
10771 // MARK: PMSettingHandle
10772
10773 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
10774
10775 void
10776 PMSettingHandle::free( void )
10777 {
10778 if (pmso) {
10779 pmso->clientHandleFreed();
10780 pmso->release();
10781 pmso = NULL;
10782 }
10783
10784 OSObject::free();
10785 }
10786
10787 // MARK: -
10788 // MARK: PMSettingObject
10789
10790 #undef super
10791 #define super OSObject
10792 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
10793
10794 /*
10795 * Static constructor/initializer for PMSettingObject
10796 */
10797 PMSettingObject *PMSettingObject::pmSettingObject(
10798 IOPMrootDomain * parent_arg,
10799 IOPMSettingControllerCallback handler_arg,
10800 OSObject * target_arg,
10801 uintptr_t refcon_arg,
10802 uint32_t supportedPowerSources,
10803 const OSSymbol * settings[],
10804 OSObject * *handle_obj)
10805 {
10806 uint32_t settingCount = 0;
10807 PMSettingObject *pmso = NULL;
10808 PMSettingHandle *pmsh = NULL;
10809
10810 if (!parent_arg || !handler_arg || !settings || !handle_obj) {
10811 return NULL;
10812 }
10813
10814 // count OSSymbol entries in NULL terminated settings array
10815 while (settings[settingCount]) {
10816 settingCount++;
10817 }
10818 if (0 == settingCount) {
10819 return NULL;
10820 }
10821
10822 pmso = new PMSettingObject;
10823 if (!pmso || !pmso->init()) {
10824 goto fail;
10825 }
10826
10827 pmsh = new PMSettingHandle;
10828 if (!pmsh || !pmsh->init()) {
10829 goto fail;
10830 }
10831
10832 queue_init(&pmso->calloutQueue);
10833 pmso->parent = parent_arg;
10834 pmso->func = handler_arg;
10835 pmso->target = target_arg;
10836 pmso->refcon = refcon_arg;
10837 pmso->settingCount = settingCount;
10838
10839 pmso->retain(); // handle holds a retain on pmso
10840 pmsh->pmso = pmso;
10841 pmso->pmsh = pmsh;
10842
10843 pmso->publishedFeatureID = (uint32_t *)IOMalloc(sizeof(uint32_t) * settingCount);
10844 if (pmso->publishedFeatureID) {
10845 for (unsigned int i = 0; i < settingCount; i++) {
10846 // Since there is now at least one listener to this setting, publish
10847 // PM root domain support for it.
10848 parent_arg->publishPMSetting( settings[i],
10849 supportedPowerSources, &pmso->publishedFeatureID[i] );
10850 }
10851 }
10852
10853 *handle_obj = pmsh;
10854 return pmso;
10855
10856 fail:
10857 if (pmso) {
10858 pmso->release();
10859 }
10860 if (pmsh) {
10861 pmsh->release();
10862 }
10863 return NULL;
10864 }
10865
10866 void
10867 PMSettingObject::free( void )
10868 {
10869 if (publishedFeatureID) {
10870 for (uint32_t i = 0; i < settingCount; i++) {
10871 if (publishedFeatureID[i]) {
10872 parent->removePublishedFeature( publishedFeatureID[i] );
10873 }
10874 }
10875
10876 IOFree(publishedFeatureID, sizeof(uint32_t) * settingCount);
10877 }
10878
10879 super::free();
10880 }
10881
10882 IOReturn
10883 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
10884 {
10885 return (*func)(target, type, object, refcon);
10886 }
10887
10888 void
10889 PMSettingObject::clientHandleFreed( void )
10890 {
10891 parent->deregisterPMSettingObject(this);
10892 }
10893
10894 // MARK: -
10895 // MARK: PMAssertionsTracker
10896
10897 //*********************************************************************************
10898 //*********************************************************************************
10899 //*********************************************************************************
10900 // class PMAssertionsTracker Implementation
10901
10902 #define kAssertUniqueIDStart 500
10903
10904 PMAssertionsTracker *
10905 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
10906 {
10907 PMAssertionsTracker *me;
10908
10909 me = new PMAssertionsTracker;
10910 if (!me || !me->init()) {
10911 if (me) {
10912 me->release();
10913 }
10914 return NULL;
10915 }
10916
10917 me->owner = rootDomain;
10918 me->issuingUniqueID = kAssertUniqueIDStart;
10919 me->assertionsArray = OSArray::withCapacity(5);
10920 me->assertionsKernel = 0;
10921 me->assertionsUser = 0;
10922 me->assertionsCombined = 0;
10923 me->assertionsArrayLock = IOLockAlloc();
10924 me->tabulateProducerCount = me->tabulateConsumerCount = 0;
10925
10926 assert(me->assertionsArray);
10927 assert(me->assertionsArrayLock);
10928
10929 return me;
10930 }
10931
10932 /* tabulate
10933 * - Update assertionsKernel to reflect the state of all
10934 * assertions in the kernel.
10935 * - Update assertionsCombined to reflect both kernel & user space.
10936 */
10937 void
10938 PMAssertionsTracker::tabulate(void)
10939 {
10940 int i;
10941 int count;
10942 PMAssertStruct *_a = NULL;
10943 OSData *_d = NULL;
10944
10945 IOPMDriverAssertionType oldKernel = assertionsKernel;
10946 IOPMDriverAssertionType oldCombined = assertionsCombined;
10947
10948 ASSERT_GATED();
10949
10950 assertionsKernel = 0;
10951 assertionsCombined = 0;
10952
10953 if (!assertionsArray) {
10954 return;
10955 }
10956
10957 if ((count = assertionsArray->getCount())) {
10958 for (i = 0; i < count; i++) {
10959 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
10960 if (_d) {
10961 _a = (PMAssertStruct *)_d->getBytesNoCopy();
10962 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
10963 assertionsKernel |= _a->assertionBits;
10964 }
10965 }
10966 }
10967 }
10968
10969 tabulateProducerCount++;
10970 assertionsCombined = assertionsKernel | assertionsUser;
10971
10972 if ((assertionsKernel != oldKernel) ||
10973 (assertionsCombined != oldCombined)) {
10974 owner->evaluateAssertions(assertionsCombined, oldCombined);
10975 }
10976 }
10977
10978 void
10979 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
10980 {
10981 AbsoluteTime now;
10982 uint64_t nsec;
10983
10984 if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
10985 (assertStruct->assertCPUStartTime == 0)) {
10986 return;
10987 }
10988
10989 now = mach_absolute_time();
10990 SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
10991 absolutetime_to_nanoseconds(now, &nsec);
10992 assertStruct->assertCPUDuration += nsec;
10993 assertStruct->assertCPUStartTime = 0;
10994
10995 if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
10996 maxAssertCPUDuration = assertStruct->assertCPUDuration;
10997 maxAssertCPUEntryId = assertStruct->registryEntryID;
10998 }
10999 }
11000
11001 void
11002 PMAssertionsTracker::reportCPUBitAccounting( void )
11003 {
11004 PMAssertStruct *_a;
11005 OSData *_d;
11006 int i, count;
11007 AbsoluteTime now;
11008 uint64_t nsec;
11009
11010 ASSERT_GATED();
11011
11012 // Account for drivers that are still holding the CPU assertion
11013 if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11014 now = mach_absolute_time();
11015 if ((count = assertionsArray->getCount())) {
11016 for (i = 0; i < count; i++) {
11017 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
11018 if (_d) {
11019 _a = (PMAssertStruct *)_d->getBytesNoCopy();
11020 if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11021 (_a->level == kIOPMDriverAssertionLevelOn) &&
11022 (_a->assertCPUStartTime != 0)) {
11023 // Don't modify PMAssertStruct, leave that
11024 // for updateCPUBitAccounting()
11025 SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11026 absolutetime_to_nanoseconds(now, &nsec);
11027 nsec += _a->assertCPUDuration;
11028 if (nsec > maxAssertCPUDuration) {
11029 maxAssertCPUDuration = nsec;
11030 maxAssertCPUEntryId = _a->registryEntryID;
11031 }
11032 }
11033 }
11034 }
11035 }
11036 }
11037
11038 if (maxAssertCPUDuration) {
11039 DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11040 (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11041 }
11042
11043 maxAssertCPUDuration = 0;
11044 maxAssertCPUEntryId = 0;
11045 }
11046
11047 void
11048 PMAssertionsTracker::publishProperties( void )
11049 {
11050 OSSharedPtr<OSArray> assertionsSummary;
11051
11052 if (tabulateConsumerCount != tabulateProducerCount) {
11053 IOLockLock(assertionsArrayLock);
11054
11055 tabulateConsumerCount = tabulateProducerCount;
11056
11057 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11058 */
11059 assertionsSummary = copyAssertionsArray();
11060 if (assertionsSummary) {
11061 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11062 } else {
11063 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11064 }
11065
11066 /* Publish the IOPMrootDomain property "DriverPMAssertions"
11067 */
11068 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11069
11070 IOLockUnlock(assertionsArrayLock);
11071 }
11072 }
11073
11074 PMAssertionsTracker::PMAssertStruct *
11075 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11076 {
11077 PMAssertStruct *_a = NULL;
11078 OSData *_d = NULL;
11079 int found = -1;
11080 int count = 0;
11081 int i = 0;
11082
11083 if (assertionsArray
11084 && (count = assertionsArray->getCount())) {
11085 for (i = 0; i < count; i++) {
11086 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
11087 if (_d) {
11088 _a = (PMAssertStruct *)_d->getBytesNoCopy();
11089 if (_a && (_id == _a->id)) {
11090 found = i;
11091 break;
11092 }
11093 }
11094 }
11095 }
11096
11097 if (-1 == found) {
11098 return NULL;
11099 } else {
11100 if (index) {
11101 *index = found;
11102 }
11103 return _a;
11104 }
11105 }
11106
11107 /* PMAssertionsTracker::handleCreateAssertion
11108 * Perform assertion work on the PM workloop. Do not call directly.
11109 */
11110 IOReturn
11111 PMAssertionsTracker::handleCreateAssertion(OSData *newAssertion)
11112 {
11113 PMAssertStruct *assertStruct;
11114
11115 ASSERT_GATED();
11116
11117 if (newAssertion) {
11118 IOLockLock(assertionsArrayLock);
11119 assertStruct = (PMAssertStruct *) newAssertion->getBytesNoCopy();
11120 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11121 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11122 assertStruct->assertCPUStartTime = mach_absolute_time();
11123 }
11124 assertionsArray->setObject(newAssertion);
11125 IOLockUnlock(assertionsArrayLock);
11126 newAssertion->release();
11127
11128 tabulate();
11129 }
11130 return kIOReturnSuccess;
11131 }
11132
11133 /* PMAssertionsTracker::createAssertion
11134 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11135 * appropiate.
11136 */
11137 IOReturn
11138 PMAssertionsTracker::createAssertion(
11139 IOPMDriverAssertionType which,
11140 IOPMDriverAssertionLevel level,
11141 IOService *serviceID,
11142 const char *whoItIs,
11143 IOPMDriverAssertionID *outID)
11144 {
11145 OSSharedPtr<OSData> dataStore;
11146 PMAssertStruct track;
11147
11148 // Warning: trillions and trillions of created assertions may overflow the unique ID.
11149 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11150 track.level = level;
11151 track.assertionBits = which;
11152
11153 // NB: ownerString is explicitly managed by PMAssertStruct
11154 // it will be released in `handleReleaseAssertion' below
11155 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11156 track.ownerService = serviceID;
11157 track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11158 track.modifiedTime = 0;
11159 pmEventTimeStamp(&track.createdTime);
11160 track.assertCPUStartTime = 0;
11161 track.assertCPUDuration = 0;
11162
11163 dataStore = OSData::withBytes(&track, sizeof(PMAssertStruct));
11164 if (!dataStore) {
11165 if (track.ownerString) {
11166 track.ownerString->release();
11167 track.ownerString = NULL;
11168 }
11169 return kIOReturnNoMemory;
11170 }
11171
11172 *outID = track.id;
11173
11174 if (owner && owner->pmPowerStateQueue) {
11175 // queue action is responsible for releasing dataStore
11176 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11177 }
11178
11179 return kIOReturnSuccess;
11180 }
11181
11182 /* PMAssertionsTracker::handleReleaseAssertion
11183 * Runs in PM workloop. Do not call directly.
11184 */
11185 IOReturn
11186 PMAssertionsTracker::handleReleaseAssertion(
11187 IOPMDriverAssertionID _id)
11188 {
11189 ASSERT_GATED();
11190
11191 int index;
11192 PMAssertStruct *assertStruct = detailsForID(_id, &index);
11193
11194 if (!assertStruct) {
11195 return kIOReturnNotFound;
11196 }
11197
11198 IOLockLock(assertionsArrayLock);
11199
11200 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11201 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11202 updateCPUBitAccounting(assertStruct);
11203 }
11204
11205 if (assertStruct->ownerString) {
11206 assertStruct->ownerString->release();
11207 assertStruct->ownerString = NULL;
11208 }
11209
11210 assertionsArray->removeObject(index);
11211 IOLockUnlock(assertionsArrayLock);
11212
11213 tabulate();
11214 return kIOReturnSuccess;
11215 }
11216
11217 /* PMAssertionsTracker::releaseAssertion
11218 * Releases an assertion and affects system behavior if appropiate.
11219 * Actual work happens on PM workloop.
11220 */
11221 IOReturn
11222 PMAssertionsTracker::releaseAssertion(
11223 IOPMDriverAssertionID _id)
11224 {
11225 if (owner && owner->pmPowerStateQueue) {
11226 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11227 }
11228 return kIOReturnSuccess;
11229 }
11230
11231 /* PMAssertionsTracker::handleSetAssertionLevel
11232 * Runs in PM workloop. Do not call directly.
11233 */
11234 IOReturn
11235 PMAssertionsTracker::handleSetAssertionLevel(
11236 IOPMDriverAssertionID _id,
11237 IOPMDriverAssertionLevel _level)
11238 {
11239 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
11240
11241 ASSERT_GATED();
11242
11243 if (!assertStruct) {
11244 return kIOReturnNotFound;
11245 }
11246
11247 IOLockLock(assertionsArrayLock);
11248 pmEventTimeStamp(&assertStruct->modifiedTime);
11249 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11250 (assertStruct->level != _level)) {
11251 if (_level == kIOPMDriverAssertionLevelOn) {
11252 assertStruct->assertCPUStartTime = mach_absolute_time();
11253 } else {
11254 updateCPUBitAccounting(assertStruct);
11255 }
11256 }
11257 assertStruct->level = _level;
11258 IOLockUnlock(assertionsArrayLock);
11259
11260 tabulate();
11261 return kIOReturnSuccess;
11262 }
11263
11264 /* PMAssertionsTracker::setAssertionLevel
11265 */
11266 IOReturn
11267 PMAssertionsTracker::setAssertionLevel(
11268 IOPMDriverAssertionID _id,
11269 IOPMDriverAssertionLevel _level)
11270 {
11271 if (owner && owner->pmPowerStateQueue) {
11272 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11273 (void *)(uintptr_t)_level, _id);
11274 }
11275
11276 return kIOReturnSuccess;
11277 }
11278
11279 IOReturn
11280 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11281 {
11282 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11283
11284 ASSERT_GATED();
11285
11286 if (new_user_levels != assertionsUser) {
11287 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11288 assertionsUser = new_user_levels;
11289 }
11290
11291 tabulate();
11292 return kIOReturnSuccess;
11293 }
11294
11295 IOReturn
11296 PMAssertionsTracker::setUserAssertionLevels(
11297 IOPMDriverAssertionType new_user_levels)
11298 {
11299 if (gIOPMWorkLoop) {
11300 gIOPMWorkLoop->runAction(
11301 OSMemberFunctionCast(
11302 IOWorkLoop::Action,
11303 this,
11304 &PMAssertionsTracker::handleSetUserAssertionLevels),
11305 this,
11306 (void *) &new_user_levels, NULL, NULL, NULL);
11307 }
11308
11309 return kIOReturnSuccess;
11310 }
11311
11312
11313 OSSharedPtr<OSArray>
11314 PMAssertionsTracker::copyAssertionsArray(void)
11315 {
11316 int count;
11317 int i;
11318 OSSharedPtr<OSArray> outArray = NULL;
11319
11320 if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11321 goto exit;
11322 }
11323 outArray = OSArray::withCapacity(count);
11324 if (!outArray) {
11325 goto exit;
11326 }
11327
11328 for (i = 0; i < count; i++) {
11329 PMAssertStruct *_a = NULL;
11330 OSData *_d = NULL;
11331 OSSharedPtr<OSDictionary> details;
11332
11333 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
11334 if (_d && (_a = (PMAssertStruct *)_d->getBytesNoCopy())) {
11335 OSSharedPtr<OSNumber> _n;
11336
11337 details = OSDictionary::withCapacity(7);
11338 if (!details) {
11339 continue;
11340 }
11341
11342 outArray->setObject(details.get());
11343
11344 _n = OSNumber::withNumber(_a->id, 64);
11345 if (_n) {
11346 details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11347 }
11348 _n = OSNumber::withNumber(_a->createdTime, 64);
11349 if (_n) {
11350 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11351 }
11352 _n = OSNumber::withNumber(_a->modifiedTime, 64);
11353 if (_n) {
11354 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11355 }
11356 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11357 if (_n) {
11358 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11359 }
11360 _n = OSNumber::withNumber(_a->level, 64);
11361 if (_n) {
11362 details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11363 }
11364 _n = OSNumber::withNumber(_a->assertionBits, 64);
11365 if (_n) {
11366 details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11367 }
11368
11369 if (_a->ownerString) {
11370 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11371 }
11372 }
11373 }
11374
11375 exit:
11376 return os::move(outArray);
11377 }
11378
11379 IOPMDriverAssertionType
11380 PMAssertionsTracker::getActivatedAssertions(void)
11381 {
11382 return assertionsCombined;
11383 }
11384
11385 IOPMDriverAssertionLevel
11386 PMAssertionsTracker::getAssertionLevel(
11387 IOPMDriverAssertionType type)
11388 {
11389 // FIXME: unused and also wrong
11390 if (type && ((type & assertionsKernel) == assertionsKernel)) {
11391 return kIOPMDriverAssertionLevelOn;
11392 } else {
11393 return kIOPMDriverAssertionLevelOff;
11394 }
11395 }
11396
11397 //*********************************************************************************
11398 //*********************************************************************************
11399 //*********************************************************************************
11400
11401
11402 static void
11403 pmEventTimeStamp(uint64_t *recordTS)
11404 {
11405 clock_sec_t tsec;
11406 clock_usec_t tusec;
11407
11408 if (!recordTS) {
11409 return;
11410 }
11411
11412 // We assume tsec fits into 32 bits; 32 bits holds enough
11413 // seconds for 136 years since the epoch in 1970.
11414 clock_get_calendar_microtime(&tsec, &tusec);
11415
11416
11417 // Pack the sec & microsec calendar time into a uint64_t, for fun.
11418 *recordTS = 0;
11419 *recordTS |= (uint32_t)tusec;
11420 *recordTS |= ((uint64_t)tsec << 32);
11421
11422 return;
11423 }
11424
11425 // MARK: -
11426 // MARK: IORootParent
11427
11428 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11429
11430 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11431
11432 // The reason that root domain needs a root parent is to facilitate demand
11433 // sleep, since a power change from the root parent cannot be vetoed.
11434 //
11435 // The above statement is no longer true since root domain now performs
11436 // demand sleep using overrides. But root parent remains to avoid changing
11437 // the power tree stacking. Root parent is parked at the max power state.
11438
11439
11440 static IOPMPowerState patriarchPowerStates[2] =
11441 {
11442 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11443 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11444 };
11445
11446 void
11447 IORootParent::initialize( void )
11448 {
11449
11450 gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
11451 gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
11452 gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
11453 gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
11454 gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
11455 gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
11456 gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
11457 gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
11458 gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
11459 gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
11460 gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
11461 gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
11462 gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
11463 gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
11464 gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
11465 gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
11466 gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
11467 gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
11468 gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
11469 gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
11470 gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
11471 gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
11472 gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
11473 gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
11474 gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
11475 gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
11476 gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
11477 gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
11478 gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
11479 gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
11480 gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
11481 gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
11482 gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
11483 gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
11484 gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
11485 gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
11486 gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
11487 gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
11488 gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
11489 gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
11490 gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
11491 gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
11492 gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
11493 gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
11494 }
11495
11496 bool
11497 IORootParent::start( IOService * nub )
11498 {
11499 IOService::start(nub);
11500 attachToParent( getRegistryRoot(), gIOPowerPlane );
11501 PMinit();
11502 registerPowerDriver(this, patriarchPowerStates, 2);
11503 makeUsable();
11504 return true;
11505 }
11506
11507 void
11508 IORootParent::shutDownSystem( void )
11509 {
11510 }
11511
11512 void
11513 IORootParent::restartSystem( void )
11514 {
11515 }
11516
11517 void
11518 IORootParent::sleepSystem( void )
11519 {
11520 }
11521
11522 void
11523 IORootParent::dozeSystem( void )
11524 {
11525 }
11526
11527 void
11528 IORootParent::sleepToDoze( void )
11529 {
11530 }
11531
11532 void
11533 IORootParent::wakeSystem( void )
11534 {
11535 }
11536
11537 OSSharedPtr<OSObject>
11538 IORootParent::copyProperty( const char * aKey) const
11539 {
11540 return IOService::copyProperty(aKey);
11541 }
11542
11543 uint32_t
11544 IOPMrootDomain::getWatchdogTimeout()
11545 {
11546 if (gSwdSleepWakeTimeout) {
11547 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11548 }
11549 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11550 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11551 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11552 } else {
11553 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11554 }
11555 }
11556
11557
11558 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11559 IOReturn
11560 IOPMrootDomain::restartWithStackshot()
11561 {
11562 takeStackshot(true);
11563
11564 return kIOReturnSuccess;
11565 }
11566
11567 void
11568 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
11569 {
11570 takeStackshot(wdogTrigger);
11571 }
11572
11573 void
11574 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
11575 {
11576 switch (tracePhase) {
11577 case kIOPMTracePointSleepStarted:
11578 *phaseString = "kIOPMTracePointSleepStarted";
11579 *description = "starting sleep";
11580 break;
11581
11582 case kIOPMTracePointSleepApplications:
11583 *phaseString = "kIOPMTracePointSleepApplications";
11584 *description = "notifying applications";
11585 break;
11586
11587 case kIOPMTracePointSleepPriorityClients:
11588 *phaseString = "kIOPMTracePointSleepPriorityClients";
11589 *description = "notifying clients about upcoming system capability changes";
11590 break;
11591
11592 case kIOPMTracePointSleepWillChangeInterests:
11593 *phaseString = "kIOPMTracePointSleepWillChangeInterests";
11594 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11595 break;
11596
11597 case kIOPMTracePointSleepPowerPlaneDrivers:
11598 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
11599 *description = "calling power state change callbacks";
11600 break;
11601
11602 case kIOPMTracePointSleepDidChangeInterests:
11603 *phaseString = "kIOPMTracePointSleepDidChangeInterests";
11604 *description = "calling rootDomain's clients about rootDomain's state changes";
11605 break;
11606
11607 case kIOPMTracePointSleepCapabilityClients:
11608 *phaseString = "kIOPMTracePointSleepCapabilityClients";
11609 *description = "notifying clients about current system capabilities";
11610 break;
11611
11612 case kIOPMTracePointSleepPlatformActions:
11613 *phaseString = "kIOPMTracePointSleepPlatformActions";
11614 *description = "calling Quiesce/Sleep action callbacks";
11615 break;
11616
11617 case kIOPMTracePointSleepCPUs:
11618 {
11619 *phaseString = "kIOPMTracePointSleepCPUs";
11620 #if defined(__i386__) || defined(__x86_64__)
11621 /*
11622 * We cannot use the getCPUNumber() method to get the cpu number, since
11623 * that cpu number is unrelated to the cpu number we need (we need the cpu
11624 * number as enumerated by the scheduler, NOT the CPU number enumerated
11625 * by ACPIPlatform as the CPUs are enumerated in MADT order).
11626 * Instead, pass the Mach processor pointer associated with the current
11627 * shutdown target so its associated cpu_id can be used in
11628 * processor_to_datastring.
11629 */
11630 if (currentShutdownTarget != NULL &&
11631 currentShutdownTarget->getMachProcessor() != NULL) {
11632 const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
11633 currentShutdownTarget->getMachProcessor());
11634 *description = sbuf;
11635 } else {
11636 *description = "halting all non-boot CPUs";
11637 }
11638 #else
11639 *description = "halting all non-boot CPUs";
11640 #endif
11641 break;
11642 }
11643 case kIOPMTracePointSleepPlatformDriver:
11644 *phaseString = "kIOPMTracePointSleepPlatformDriver";
11645 *description = "executing platform specific code";
11646 break;
11647
11648 case kIOPMTracePointHibernate:
11649 *phaseString = "kIOPMTracePointHibernate";
11650 *description = "writing the hibernation image";
11651 break;
11652
11653 case kIOPMTracePointSystemSleep:
11654 *phaseString = "kIOPMTracePointSystemSleep";
11655 *description = "in EFI/Bootrom after last point of entry to sleep";
11656 break;
11657
11658 case kIOPMTracePointWakePlatformDriver:
11659 *phaseString = "kIOPMTracePointWakePlatformDriver";
11660 *description = "executing platform specific code";
11661 break;
11662
11663
11664 case kIOPMTracePointWakePlatformActions:
11665 *phaseString = "kIOPMTracePointWakePlatformActions";
11666 *description = "calling Wake action callbacks";
11667 break;
11668
11669 case kIOPMTracePointWakeCPUs:
11670 *phaseString = "kIOPMTracePointWakeCPUs";
11671 *description = "starting non-boot CPUs";
11672 break;
11673
11674 case kIOPMTracePointWakeWillPowerOnClients:
11675 *phaseString = "kIOPMTracePointWakeWillPowerOnClients";
11676 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
11677 break;
11678
11679 case kIOPMTracePointWakeWillChangeInterests:
11680 *phaseString = "kIOPMTracePointWakeWillChangeInterests";
11681 *description = "calling rootDomain's clients about upcoming rootDomain's state changes";
11682 break;
11683
11684 case kIOPMTracePointWakeDidChangeInterests:
11685 *phaseString = "kIOPMTracePointWakeDidChangeInterests";
11686 *description = "calling rootDomain's clients about completed rootDomain's state changes";
11687 break;
11688
11689 case kIOPMTracePointWakePowerPlaneDrivers:
11690 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
11691 *description = "calling power state change callbacks";
11692 break;
11693
11694 case kIOPMTracePointWakeCapabilityClients:
11695 *phaseString = "kIOPMTracePointWakeCapabilityClients";
11696 *description = "informing clients about current system capabilities";
11697 break;
11698
11699 case kIOPMTracePointWakeApplications:
11700 *phaseString = "kIOPMTracePointWakeApplications";
11701 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
11702 break;
11703
11704 case kIOPMTracePointDarkWakeEntry:
11705 *phaseString = "kIOPMTracePointDarkWakeEntry";
11706 *description = "entering darkwake on way to sleep";
11707 break;
11708
11709 case kIOPMTracePointDarkWakeExit:
11710 *phaseString = "kIOPMTracePointDarkWakeExit";
11711 *description = "entering fullwake from darkwake";
11712 break;
11713
11714 default:
11715 *phaseString = NULL;
11716 *description = NULL;
11717 }
11718 }
11719
11720 void
11721 IOPMrootDomain::saveFailureData2File()
11722 {
11723 unsigned int len = 0;
11724 char failureStr[512];
11725 errno_t error;
11726 char *outbuf;
11727 OSNumber *statusCode;
11728 uint64_t pmStatusCode = 0;
11729 uint32_t phaseData = 0;
11730 uint32_t phaseDetail = 0;
11731 bool efiFailure = false;
11732
11733 OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
11734 statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
11735 if (statusCode) {
11736 pmStatusCode = statusCode->unsigned64BitValue();
11737 phaseData = pmStatusCode & 0xFFFFFFFF;
11738 phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
11739 if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
11740 LOG("Sleep Wake failure in EFI\n");
11741 efiFailure = true;
11742 failureStr[0] = 0;
11743 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);
11744 len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
11745 }
11746 }
11747
11748 if (!efiFailure) {
11749 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
11750 swd_flags |= SWD_BOOT_BY_SW_WDOG;
11751 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
11752 // dump panic will handle saving nvram data
11753 return;
11754 }
11755
11756 /* Keeping this around for capturing data during power
11757 * button press */
11758
11759 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
11760 DLOG("No sleep wake failure string\n");
11761 return;
11762 }
11763 if (len == 0) {
11764 DLOG("Ignoring zero byte SleepWake failure string\n");
11765 goto exit;
11766 }
11767
11768 // if PMStatus code is zero, delete stackshot and return
11769 if (statusCode) {
11770 if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
11771 // there was no sleep wake failure
11772 // this can happen if delete stackshot was called
11773 // before take stackshot completed. Let us delete any
11774 // sleep wake failure data in nvram
11775 DLOG("Deleting stackshot on successful wake\n");
11776 deleteStackshot();
11777 return;
11778 }
11779 }
11780
11781 if (len > sizeof(failureStr)) {
11782 len = sizeof(failureStr);
11783 }
11784 failureStr[0] = 0;
11785 PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
11786 }
11787 if (failureStr[0] != 0) {
11788 error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
11789 if (error) {
11790 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
11791 } else {
11792 DLOG("Saved SleepWake failure string to file.\n");
11793 }
11794 }
11795
11796 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
11797 goto exit;
11798 }
11799
11800 if (swd_buffer) {
11801 unsigned int len = 0;
11802 errno_t error;
11803 char nvram_var_name_buffer[20];
11804 unsigned int concat_len = 0;
11805 swd_hdr *hdr = NULL;
11806
11807
11808 hdr = (swd_hdr *)swd_buffer;
11809 outbuf = (char *)hdr + hdr->spindump_offset;
11810 OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
11811
11812 for (int i = 0; i < 8; i++) {
11813 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
11814 if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
11815 LOG("No SleepWake blob to read beyond chunk %d\n", i);
11816 break;
11817 }
11818 if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
11819 PERemoveNVRAMProperty(nvram_var_name_buffer);
11820 LOG("Could not read the property :-(\n");
11821 break;
11822 }
11823 PERemoveNVRAMProperty(nvram_var_name_buffer);
11824 concat_len += len;
11825 }
11826 LOG("Concatenated length for the SWD blob %d\n", concat_len);
11827
11828 if (concat_len) {
11829 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
11830 if (error) {
11831 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
11832 } else {
11833 LOG("Saved SleepWake zipped data to file.\n");
11834 }
11835 } else {
11836 // There is a sleep wake failure string but no stackshot
11837 // Write a placeholder stacks file so that swd runs
11838 snprintf(outbuf, 20, "%s", "No stackshot data\n");
11839 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
11840 if (error) {
11841 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
11842 } else {
11843 LOG("Saved SleepWake zipped data to file.\n");
11844 }
11845 }
11846 } else {
11847 LOG("No buffer allocated to save failure stackshot\n");
11848 }
11849
11850
11851 gRootDomain->swd_lock = 0;
11852 exit:
11853 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
11854 return;
11855 }
11856
11857
11858 void
11859 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
11860 {
11861 OSSharedPtr<IORegistryIterator> iter;
11862 OSSharedPtr<const OSSymbol> kextName = NULL;
11863 IORegistryEntry * entry;
11864 IOService * node;
11865 bool nodeFound = false;
11866
11867 const void * callMethod = NULL;
11868 const char * objectName = NULL;
11869 uint32_t timeout = getWatchdogTimeout();
11870 const char * phaseString = NULL;
11871 const char * phaseDescription = NULL;
11872
11873 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
11874 uint32_t tracePhase = pmTracer->getTracePhase();
11875
11876 *thread = NULL;
11877 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
11878 snprintf(failureStr, strLen, "Sleep transition timed out after %d seconds", timeout);
11879 } else {
11880 snprintf(failureStr, strLen, "Wake transition timed out after %d seconds", timeout);
11881 }
11882 tracePhase2String(tracePhase, &phaseString, &phaseDescription);
11883
11884 if (notifierThread) {
11885 if (notifier && (notifier->identifier)) {
11886 objectName = notifier->identifier->getCStringNoCopy();
11887 }
11888 *thread = notifierThread;
11889 } else {
11890 iter = IORegistryIterator::iterateOver(
11891 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
11892
11893 if (iter) {
11894 while ((entry = iter->getNextObject())) {
11895 node = OSDynamicCast(IOService, entry);
11896 if (!node) {
11897 continue;
11898 }
11899 if (OSDynamicCast(IOPowerConnection, node)) {
11900 continue;
11901 }
11902
11903 if (node->getBlockingDriverCall(thread, &callMethod)) {
11904 nodeFound = true;
11905 break;
11906 }
11907 }
11908 }
11909 if (nodeFound) {
11910 kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
11911 if (kextName) {
11912 objectName = kextName->getCStringNoCopy();
11913 }
11914 }
11915 }
11916 if (phaseDescription) {
11917 strlcat(failureStr, " while ", strLen);
11918 strlcat(failureStr, phaseDescription, strLen);
11919 strlcat(failureStr, ".", strLen);
11920 }
11921 if (objectName) {
11922 strlcat(failureStr, " Suspected bundle: ", strLen);
11923 strlcat(failureStr, objectName, strLen);
11924 strlcat(failureStr, ".", strLen);
11925 }
11926 if (*thread) {
11927 char threadName[40];
11928 snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
11929 strlcat(failureStr, threadName, strLen);
11930 }
11931
11932 DLOG("%s\n", failureStr);
11933 }
11934
11935 struct swd_stackshot_compressed_data {
11936 z_output_func zoutput;
11937 size_t zipped;
11938 uint64_t totalbytes;
11939 uint64_t lastpercent;
11940 IOReturn error;
11941 unsigned outremain;
11942 unsigned outlen;
11943 unsigned writes;
11944 Bytef * outbuf;
11945 };
11946 struct swd_stackshot_compressed_data swd_zip_var = { };
11947
11948 static void *
11949 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
11950 {
11951 void *result;
11952 LOG("Alloc in zipping %d items of size %d\n", items, size);
11953
11954 result = (void *)(swd_zs_zmem + swd_zs_zoffset);
11955 swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
11956 LOG("Offset %zu\n", swd_zs_zoffset);
11957 return result;
11958 }
11959
11960 static int
11961 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
11962 {
11963 unsigned len;
11964
11965 len = strm->avail_in;
11966
11967 if (len > size) {
11968 len = size;
11969 }
11970 if (len == 0) {
11971 return 0;
11972 }
11973
11974 if (strm->next_in != (Bytef *) strm) {
11975 memcpy(buf, strm->next_in, len);
11976 } else {
11977 bzero(buf, len);
11978 }
11979
11980 strm->adler = z_crc32(strm->adler, buf, len);
11981
11982 strm->avail_in -= len;
11983 strm->next_in += len;
11984 strm->total_in += len;
11985
11986 return (int)len;
11987 }
11988
11989 static int
11990 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
11991 {
11992 unsigned int i = 0;
11993 // if outlen > max size don't add to the buffer
11994 assert(buf != NULL);
11995 if (strm && buf) {
11996 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
11997 LOG("No space to GZIP... not writing to NVRAM\n");
11998 return len;
11999 }
12000 }
12001 for (i = 0; i < len; i++) {
12002 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12003 }
12004 swd_zip_var.outlen += len;
12005 return len;
12006 }
12007
12008 static void
12009 swd_zs_free(void * __unused ref, void * __unused ptr)
12010 {
12011 }
12012
12013 static int
12014 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12015 {
12016 int wbits = 12;
12017 int memlevel = 3;
12018
12019 if (((unsigned int) numBytes) != numBytes) {
12020 return 0;
12021 }
12022
12023 if (!swd_zs.zalloc) {
12024 swd_zs.zalloc = swd_zs_alloc;
12025 swd_zs.zfree = swd_zs_free;
12026 if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12027 // allocation failed
12028 bzero(&swd_zs, sizeof(swd_zs));
12029 // swd_zs_zoffset = 0;
12030 } else {
12031 LOG("PMRD inited the zlib allocation routines\n");
12032 }
12033 }
12034
12035 swd_zip_var.zipped = 0;
12036 swd_zip_var.totalbytes = 0; // should this be the max that we have?
12037 swd_zip_var.lastpercent = 0;
12038 swd_zip_var.error = kIOReturnSuccess;
12039 swd_zip_var.outremain = 0;
12040 swd_zip_var.outlen = 0;
12041 swd_zip_var.writes = 0;
12042 swd_zip_var.outbuf = (Bytef *)outPtr;
12043
12044 swd_zip_var.totalbytes = numBytes;
12045
12046 swd_zs.avail_in = 0;
12047 swd_zs.next_in = NULL;
12048 swd_zs.avail_out = 0;
12049 swd_zs.next_out = NULL;
12050
12051 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12052
12053 z_stream *zs;
12054 int zr;
12055 zs = &swd_zs;
12056
12057 while (swd_zip_var.error >= 0) {
12058 if (!zs->avail_in) {
12059 zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12060 zs->avail_in = (unsigned int) numBytes;
12061 }
12062 if (!zs->avail_out) {
12063 zs->next_out = (Bytef *)zs;
12064 zs->avail_out = UINT32_MAX;
12065 }
12066 zr = deflate(zs, Z_NO_FLUSH);
12067 if (Z_STREAM_END == zr) {
12068 break;
12069 }
12070 if (zr != Z_OK) {
12071 LOG("ZERR %d\n", zr);
12072 swd_zip_var.error = zr;
12073 } else {
12074 if (zs->total_in == numBytes) {
12075 break;
12076 }
12077 }
12078 }
12079
12080 //now flush the stream
12081 while (swd_zip_var.error >= 0) {
12082 if (!zs->avail_out) {
12083 zs->next_out = (Bytef *)zs;
12084 zs->avail_out = UINT32_MAX;
12085 }
12086 zr = deflate(zs, Z_FINISH);
12087 if (Z_STREAM_END == zr) {
12088 break;
12089 }
12090 if (zr != Z_OK) {
12091 LOG("ZERR %d\n", zr);
12092 swd_zip_var.error = zr;
12093 } else {
12094 if (zs->total_in == numBytes) {
12095 LOG("Total output size %d\n", swd_zip_var.outlen);
12096 break;
12097 }
12098 }
12099 }
12100
12101 return swd_zip_var.outlen;
12102 }
12103
12104 void
12105 IOPMrootDomain::deleteStackshot()
12106 {
12107 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12108 // takeStackshot hasn't completed
12109 return;
12110 }
12111 LOG("Deleting any sleepwake failure data in nvram\n");
12112
12113 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12114 char nvram_var_name_buf[20];
12115 for (int i = 0; i < 8; i++) {
12116 snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12117 if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12118 LOG("Removing %s returned false\n", nvram_var_name_buf);
12119 }
12120 }
12121 // force NVRAM sync
12122 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12123 DLOG("Failed to force nvram sync\n");
12124 }
12125 gRootDomain->swd_lock = 0;
12126 }
12127
12128 void
12129 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12130 {
12131 swd_hdr * hdr = NULL;
12132 int cnt = 0;
12133 int max_cnt = 2;
12134 pid_t pid = 0;
12135 kern_return_t kr = KERN_SUCCESS;
12136 uint64_t flags;
12137
12138 char * dstAddr;
12139 uint32_t size;
12140 uint32_t bytesRemaining;
12141 unsigned bytesWritten = 0;
12142
12143 char failureStr[512];
12144 thread_t thread = NULL;
12145 const char * swfPanic = "swfPanic";
12146
12147 uint32_t bufSize;
12148 int success = 0;
12149
12150 #if defined(__i386__) || defined(__x86_64__)
12151 const bool concise = false;
12152 #else
12153 const bool concise = true;
12154 #endif
12155
12156 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12157 return;
12158 }
12159
12160 failureStr[0] = 0;
12161 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12162 return;
12163 }
12164
12165 if (wdogTrigger) {
12166 getFailureData(&thread, failureStr, sizeof(failureStr));
12167
12168 if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12169 goto skip_stackshot;
12170 }
12171 } else {
12172 AbsoluteTime now;
12173 uint64_t nsec;
12174 clock_get_uptime(&now);
12175 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12176 absolutetime_to_nanoseconds(now, &nsec);
12177 snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12178 }
12179
12180 if (swd_buffer == NULL) {
12181 sleepWakeDebugMemAlloc();
12182 if (swd_buffer == NULL) {
12183 return;
12184 }
12185 }
12186 hdr = (swd_hdr *)swd_buffer;
12187 bufSize = hdr->alloc_size;
12188
12189 dstAddr = (char*)hdr + hdr->spindump_offset;
12190 flags = STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_THREAD_WAITINFO;
12191 /* If not wdogTrigger only take kernel tasks stackshot
12192 */
12193 if (wdogTrigger) {
12194 pid = -1;
12195 } else {
12196 pid = 0;
12197 }
12198
12199 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12200 * If we run out of space, take stackshot with only kernel task
12201 */
12202 while (success == 0 && cnt < max_cnt) {
12203 bytesRemaining = bufSize - hdr->spindump_offset;
12204 cnt++;
12205 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12206
12207 size = bytesRemaining;
12208 kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12209 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12210 kr, pid, size, flags, bytesWritten);
12211 if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12212 if (pid == -1) {
12213 pid = 0;
12214 } else {
12215 LOG("Insufficient buffer size for only kernel task\n");
12216 break;
12217 }
12218 }
12219 if (kr == KERN_SUCCESS) {
12220 if (bytesWritten == 0) {
12221 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12222 continue;
12223 }
12224 bytesRemaining -= bytesWritten;
12225 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12226
12227 memset(hdr->reason, 0x20, sizeof(hdr->reason));
12228
12229 // Compress stackshot and save to NVRAM
12230 {
12231 char *outbuf = (char *)swd_compressed_buffer;
12232 int outlen = 0;
12233 int num_chunks = 0;
12234 int max_chunks = 0;
12235 int leftover = 0;
12236 char nvram_var_name_buffer[20];
12237
12238 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12239
12240 if (outlen) {
12241 max_chunks = outlen / (2096 - 200);
12242 leftover = outlen % (2096 - 200);
12243
12244 if (max_chunks < 8) {
12245 for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
12246 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12247 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
12248 LOG("Failed to update NVRAM %d\n", num_chunks);
12249 break;
12250 }
12251 }
12252 if (leftover) {
12253 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12254 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
12255 LOG("Failed to update NVRAM with leftovers\n");
12256 }
12257 }
12258 success = 1;
12259 LOG("Successfully saved stackshot to NVRAM\n");
12260 } else {
12261 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12262 if (pid == -1) {
12263 pid = 0;
12264 } else {
12265 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12266 break;
12267 }
12268 }
12269 }
12270 }
12271 }
12272 }
12273
12274 if (failureStr[0]) {
12275 // append sleep-wake failure code
12276 char traceCode[80];
12277 snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
12278 pmTracer->getTraceData(), pmTracer->getTracePhase());
12279 strlcat(failureStr, traceCode, sizeof(failureStr));
12280 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
12281 DLOG("Failed to write SleepWake failure string\n");
12282 }
12283 }
12284
12285 // force NVRAM sync
12286 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12287 DLOG("Failed to force nvram sync\n");
12288 }
12289
12290 skip_stackshot:
12291 if (wdogTrigger) {
12292 if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
12293 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
12294 // If current boot is due to this watch dog trigger restart in previous boot,
12295 // then don't trigger again until at least 1 successful sleep & wake.
12296 if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
12297 LOG("Shutting down due to repeated Sleep/Wake failures\n");
12298 if (!tasksSuspended) {
12299 tasksSuspended = TRUE;
12300 updateTasksSuspend();
12301 }
12302 PEHaltRestart(kPEHaltCPU);
12303 return;
12304 }
12305 }
12306 if (gSwdPanic == 0) {
12307 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12308 if (!tasksSuspended) {
12309 tasksSuspended = TRUE;
12310 updateTasksSuspend();
12311 }
12312 PEHaltRestart(kPERestartCPU);
12313 }
12314 }
12315 if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12316 DLOG("Failed to write SleepWake failure panic key\n");
12317 }
12318 #if defined(__x86_64__)
12319 if (thread) {
12320 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12321 } else
12322 #endif /* defined(__x86_64__) */
12323 {
12324 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12325 }
12326 } else {
12327 gRootDomain->swd_lock = 0;
12328 return;
12329 }
12330 }
12331
12332 void
12333 IOPMrootDomain::sleepWakeDebugMemAlloc()
12334 {
12335 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12336
12337 swd_hdr *hdr = NULL;
12338 void *bufPtr = NULL;
12339
12340 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12341
12342
12343 if (kIOSleepWakeWdogOff & gIOKitDebug) {
12344 return;
12345 }
12346
12347 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12348 return;
12349 }
12350
12351 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12352 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12353 size);
12354 if (memDesc == NULL) {
12355 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12356 goto exit;
12357 }
12358
12359 bufPtr = memDesc->getBytesNoCopy();
12360
12361 // Carve out memory for zlib routines
12362 swd_zs_zmem = (vm_offset_t)bufPtr;
12363 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12364
12365 // Carve out memory for compressed stackshots
12366 swd_compressed_buffer = bufPtr;
12367 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12368
12369 // Remaining is used for holding stackshot
12370 hdr = (swd_hdr *)bufPtr;
12371 memset(hdr, 0, sizeof(swd_hdr));
12372
12373 hdr->signature = SWD_HDR_SIGNATURE;
12374 hdr->alloc_size = SWD_STACKSHOT_SIZE;
12375
12376 hdr->spindump_offset = sizeof(swd_hdr);
12377 swd_buffer = (void *)hdr;
12378 swd_memDesc = os::move(memDesc);
12379 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
12380
12381 exit:
12382 gRootDomain->swd_lock = 0;
12383 }
12384
12385 void
12386 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12387 {
12388 #if UNUSED
12389 vm_size_t size = SWD_SPINDUMP_SIZE;
12390
12391 swd_hdr *hdr = NULL;
12392
12393 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12394
12395 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12396 return;
12397 }
12398
12399 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12400 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12401 SWD_SPINDUMP_SIZE);
12402
12403 if (memDesc == NULL) {
12404 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12405 goto exit;
12406 }
12407
12408
12409 hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12410 memset(hdr, 0, sizeof(swd_hdr));
12411
12412 hdr->signature = SWD_HDR_SIGNATURE;
12413 hdr->alloc_size = size;
12414
12415 hdr->spindump_offset = sizeof(swd_hdr);
12416 swd_spindump_buffer = (void *)hdr;
12417 swd_spindump_memDesc = os::move(memDesc);
12418
12419 exit:
12420 gRootDomain->swd_lock = 0;
12421 #endif /* UNUSED */
12422 }
12423
12424 void
12425 IOPMrootDomain::sleepWakeDebugEnableWdog()
12426 {
12427 }
12428
12429 bool
12430 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12431 {
12432 return !systemBooting && !systemShutdown && !gWillShutdown;
12433 }
12434
12435 void
12436 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12437 {
12438 swd_hdr *hdr = NULL;
12439 errno_t error = EIO;
12440
12441 if (swd_spindump_buffer && gSpinDumpBufferFull) {
12442 hdr = (swd_hdr *)swd_spindump_buffer;
12443
12444 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12445 (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12446
12447 if (error) {
12448 return;
12449 }
12450
12451 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12452 (char*)hdr + offsetof(swd_hdr, UUID),
12453 sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12454
12455 gSpinDumpBufferFull = false;
12456 }
12457 }
12458
12459 errno_t
12460 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12461 {
12462 struct vnode *vp = NULL;
12463 vfs_context_t ctx = vfs_context_create(vfs_context_current());
12464 kauth_cred_t cred = vfs_context_ucred(ctx);
12465 struct vnode_attr va;
12466 errno_t error = EIO;
12467
12468 if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
12469 S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
12470 LOG("Failed to open the file %s\n", name);
12471 swd_flags |= SWD_FILEOP_ERROR;
12472 goto exit;
12473 }
12474 VATTR_INIT(&va);
12475 VATTR_WANTED(&va, va_nlink);
12476 /* Don't dump to non-regular files or files with links. */
12477 if (vp->v_type != VREG ||
12478 vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
12479 LOG("Bailing as this is not a regular file\n");
12480 swd_flags |= SWD_FILEOP_ERROR;
12481 goto exit;
12482 }
12483 VATTR_INIT(&va);
12484 VATTR_SET(&va, va_data_size, 0);
12485 vnode_setattr(vp, &va, ctx);
12486
12487
12488 if (buf != NULL) {
12489 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12490 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12491 if (error != 0) {
12492 LOG("Failed to save sleep wake log. err 0x%x\n", error);
12493 swd_flags |= SWD_FILEOP_ERROR;
12494 } else {
12495 DLOG("Saved %d bytes to file %s\n", len, name);
12496 }
12497 }
12498
12499 exit:
12500 if (vp) {
12501 vnode_close(vp, FWRITE, ctx);
12502 }
12503 if (ctx) {
12504 vfs_context_rele(ctx);
12505 }
12506
12507 return error;
12508 }
12509
12510 #else /* defined(__i386__) || defined(__x86_64__) */
12511
12512 void
12513 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12514 {
12515 if (restart) {
12516 if (gSwdPanic == 0) {
12517 return;
12518 }
12519 panic("Sleep/Wake hang detected");
12520 return;
12521 }
12522 }
12523
12524 void
12525 IOPMrootDomain::takeStackshot(bool restart)
12526 {
12527 #pragma unused(restart)
12528 }
12529
12530 void
12531 IOPMrootDomain::deleteStackshot()
12532 {
12533 }
12534
12535 void
12536 IOPMrootDomain::sleepWakeDebugMemAlloc()
12537 {
12538 }
12539
12540 void
12541 IOPMrootDomain::saveFailureData2File()
12542 {
12543 }
12544
12545 void
12546 IOPMrootDomain::sleepWakeDebugEnableWdog()
12547 {
12548 }
12549
12550 bool
12551 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12552 {
12553 return false;
12554 }
12555
12556 void
12557 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12558 {
12559 }
12560
12561 errno_t
12562 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12563 {
12564 return 0;
12565 }
12566
12567 #endif /* defined(__i386__) || defined(__x86_64__) */
12568