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