1 /*
2 * Copyright (c) 1998-2021 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++/OSAllocation.h>
32 #include <libkern/c++/OSKext.h>
33 #include <libkern/c++/OSMetaClass.h>
34 #include <libkern/OSAtomic.h>
35 #include <libkern/OSDebug.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommandGate.h>
38 #include <IOKit/IOTimerEventSource.h>
39 #include <IOKit/IOPlatformExpert.h>
40 #include <IOKit/IOCPU.h>
41 #include <IOKit/IOPlatformActions.h>
42 #include <IOKit/IOKitDebug.h>
43 #include <IOKit/IOTimeStamp.h>
44 #include <IOKit/pwr_mgt/IOPMlog.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
46 #include <IOKit/pwr_mgt/IOPMPrivate.h>
47 #include <IOKit/IODeviceTreeSupport.h>
48 #include <IOKit/IOMessage.h>
49 #include <IOKit/IOReturn.h>
50 #include <IOKit/IONVRAM.h>
51 #include "RootDomainUserClient.h"
52 #include "IOKit/pwr_mgt/IOPowerConnection.h"
53 #include "IOPMPowerStateQueue.h"
54 #include <IOKit/IOCatalogue.h>
55 #include <IOKit/IOReportMacros.h>
56 #include <IOKit/IOLib.h>
57 #include <IOKit/IOKitKeys.h>
58 #include <IOKit/IOUserServer.h>
59 #include <IOKit/IOBSD.h>
60 #include "IOKitKernelInternal.h"
61 #if HIBERNATION
62 #include <IOKit/IOHibernatePrivate.h>
63 #endif /* HIBERNATION */
64 #include <machine/machine_routines.h>
65 #include <console/video_console.h>
66 #include <sys/syslog.h>
67 #include <sys/sysctl.h>
68 #include <sys/vnode.h>
69 #include <sys/vnode_internal.h>
70 #include <sys/fcntl.h>
71 #include <os/log.h>
72 #include <pexpert/device_tree.h>
73 #include <pexpert/protos.h>
74 #include <AssertMacros.h>
75
76 #include <sys/time.h>
77 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
78 #include "IOServicePMPrivate.h"
79
80 #include <libkern/zlib.h>
81 #include <os/cpp_util.h>
82 #include <os/atomic_private.h>
83 #include <libkern/c++/OSBoundedArrayRef.h>
84
85 #if DEVELOPMENT || DEBUG
86 #include <os/system_event_log.h>
87 #endif /* DEVELOPMENT || DEBUG */
88
89 __BEGIN_DECLS
90 #include <mach/shared_region.h>
91 #include <kern/clock.h>
92 #include <vm/vm_pageout_xnu.h>
93 __END_DECLS
94
95 #if defined(__i386__) || defined(__x86_64__)
96 __BEGIN_DECLS
97 #include "IOPMrootDomainInternal.h"
98 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
99 __END_DECLS
100 #endif
101
102 #define kIOPMrootDomainClass "IOPMrootDomain"
103 #define LOG_PREFIX "PMRD: "
104
105
106 #define MSG(x...) \
107 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
108
109 #define LOG(x...) \
110 do { kprintf(LOG_PREFIX x); } while (false)
111
112 #if DEVELOPMENT || DEBUG
113 #define DEBUG_LOG(x...) do { \
114 if (kIOLogPMRootDomain & gIOKitDebug) \
115 kprintf(LOG_PREFIX x); \
116 os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
117 } while (false)
118 #else
119 #define DEBUG_LOG(x...)
120 #endif
121
122 #define DLOG(x...) do { \
123 if (kIOLogPMRootDomain & gIOKitDebug) \
124 IOLog(LOG_PREFIX x); \
125 else \
126 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
127 } while (false)
128
129 #define DMSG(x...) do { \
130 if (kIOLogPMRootDomain & gIOKitDebug) { \
131 kprintf(LOG_PREFIX x); \
132 } \
133 } while (false)
134
135
136 #define _LOG(x...)
137
138 #define CHECK_THREAD_CONTEXT
139 #ifdef CHECK_THREAD_CONTEXT
140 static IOWorkLoop * gIOPMWorkLoop = NULL;
141 #define ASSERT_GATED() \
142 do { \
143 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
144 panic("RootDomain: not inside PM gate"); \
145 } \
146 } while(false)
147 #else
148 #define ASSERT_GATED()
149 #endif /* CHECK_THREAD_CONTEXT */
150
151 #define CAP_LOSS(c) \
152 (((_pendingCapability & (c)) == 0) && \
153 ((_currentCapability & (c)) != 0))
154
155 #define CAP_GAIN(c) \
156 (((_currentCapability & (c)) == 0) && \
157 ((_pendingCapability & (c)) != 0))
158
159 #define CAP_CHANGE(c) \
160 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
161
162 #define CAP_CURRENT(c) \
163 ((_currentCapability & (c)) != 0)
164
165 #define CAP_HIGHEST(c) \
166 ((_highestCapability & (c)) != 0)
167
168 #define CAP_PENDING(c) \
169 ((_pendingCapability & (c)) != 0)
170
171 // rdar://problem/9157444
172 #if defined(__i386__) || defined(__x86_64__)
173 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 20
174 #endif
175
176 // Event types for IOPMPowerStateQueue::submitPowerEvent()
177 enum {
178 kPowerEventFeatureChanged = 1, // 1
179 kPowerEventReceivedPowerNotification, // 2
180 kPowerEventSystemBootCompleted, // 3
181 kPowerEventSystemShutdown, // 4
182 kPowerEventUserDisabledSleep, // 5
183 kPowerEventRegisterSystemCapabilityClient, // 6
184 kPowerEventRegisterKernelCapabilityClient, // 7
185 kPowerEventPolicyStimulus, // 8
186 kPowerEventAssertionCreate, // 9
187 kPowerEventAssertionRelease, // 10
188 kPowerEventAssertionSetLevel, // 11
189 kPowerEventQueueSleepWakeUUID, // 12
190 kPowerEventPublishSleepWakeUUID, // 13
191 kPowerEventSetDisplayPowerOn, // 14
192 kPowerEventPublishWakeType, // 15
193 kPowerEventAOTEvaluate, // 16
194 kPowerEventRunModeRequest // 17
195 };
196
197 // For evaluatePolicy()
198 // List of stimuli that affects the root domain policy.
199 enum {
200 kStimulusDisplayWranglerSleep, // 0
201 kStimulusDisplayWranglerWake, // 1
202 kStimulusAggressivenessChanged, // 2
203 kStimulusDemandSystemSleep, // 3
204 kStimulusAllowSystemSleepChanged, // 4
205 kStimulusDarkWakeActivityTickle, // 5
206 kStimulusDarkWakeEntry, // 6
207 kStimulusDarkWakeReentry, // 7
208 kStimulusDarkWakeEvaluate, // 8
209 kStimulusNoIdleSleepPreventers, // 9
210 kStimulusEnterUserActiveState, // 10
211 kStimulusLeaveUserActiveState // 11
212 };
213
214 // Internal power state change reasons
215 // Must be less than kIOPMSleepReasonClamshell=101
216 enum {
217 kCPSReasonNone = 0, // 0
218 kCPSReasonInit, // 1
219 kCPSReasonWake, // 2
220 kCPSReasonIdleSleepPrevent, // 3
221 kCPSReasonIdleSleepAllow, // 4
222 kCPSReasonPowerOverride, // 5
223 kCPSReasonPowerDownCancel, // 6
224 kCPSReasonAOTExit, // 7
225 kCPSReasonAdjustPowerState, // 8
226 kCPSReasonDarkWakeCannotSleep, // 9
227 kCPSReasonIdleSleepEnabled, // 10
228 kCPSReasonEvaluatePolicy, // 11
229 kCPSReasonSustainFullWake, // 12
230 kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1)
231 };
232
233 extern "C" {
234 IOReturn OSKextSystemSleepOrWake( UInt32 );
235 }
236 extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
237 extern "C" addr64_t kvtophys(vm_offset_t va);
238 extern "C" boolean_t kdp_has_polled_corefile();
239
240 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
241 static void notifySystemShutdown( IOService * root, uint32_t messageType );
242 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
243 static void pmEventTimeStamp(uint64_t *recordTS);
244 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
245 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
246 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address);
247
248 static int IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt);
249 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
250 #define YMDTF "%04d/%02d/%d %02d:%02d:%02d"
251 #define YMDT(cal) ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
252
253 // "IOPMSetSleepSupported" callPlatformFunction name
254 static OSSharedPtr<const OSSymbol> sleepSupportedPEFunction;
255 static OSSharedPtr<const OSSymbol> sleepMessagePEFunction;
256 static OSSharedPtr<const OSSymbol> gIOPMWakeTypeUserKey;
257
258 static OSSharedPtr<const OSSymbol> gIOPMPSExternalConnectedKey;
259 static OSSharedPtr<const OSSymbol> gIOPMPSExternalChargeCapableKey;
260 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryInstalledKey;
261 static OSSharedPtr<const OSSymbol> gIOPMPSIsChargingKey;
262 static OSSharedPtr<const OSSymbol> gIOPMPSAtWarnLevelKey;
263 static OSSharedPtr<const OSSymbol> gIOPMPSAtCriticalLevelKey;
264 static OSSharedPtr<const OSSymbol> gIOPMPSCurrentCapacityKey;
265 static OSSharedPtr<const OSSymbol> gIOPMPSMaxCapacityKey;
266 static OSSharedPtr<const OSSymbol> gIOPMPSDesignCapacityKey;
267 static OSSharedPtr<const OSSymbol> gIOPMPSTimeRemainingKey;
268 static OSSharedPtr<const OSSymbol> gIOPMPSAmperageKey;
269 static OSSharedPtr<const OSSymbol> gIOPMPSVoltageKey;
270 static OSSharedPtr<const OSSymbol> gIOPMPSCycleCountKey;
271 static OSSharedPtr<const OSSymbol> gIOPMPSMaxErrKey;
272 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterInfoKey;
273 static OSSharedPtr<const OSSymbol> gIOPMPSLocationKey;
274 static OSSharedPtr<const OSSymbol> gIOPMPSErrorConditionKey;
275 static OSSharedPtr<const OSSymbol> gIOPMPSManufacturerKey;
276 static OSSharedPtr<const OSSymbol> gIOPMPSManufactureDateKey;
277 static OSSharedPtr<const OSSymbol> gIOPMPSModelKey;
278 static OSSharedPtr<const OSSymbol> gIOPMPSSerialKey;
279 static OSSharedPtr<const OSSymbol> gIOPMPSLegacyBatteryInfoKey;
280 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryHealthKey;
281 static OSSharedPtr<const OSSymbol> gIOPMPSHealthConfidenceKey;
282 static OSSharedPtr<const OSSymbol> gIOPMPSCapacityEstimatedKey;
283 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryChargeStatusKey;
284 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryTemperatureKey;
285 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsKey;
286 static OSSharedPtr<const OSSymbol> gIOPMPSChargerConfigurationKey;
287 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsIDKey;
288 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsWattsKey;
289 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsRevisionKey;
290 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSerialNumberKey;
291 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsFamilyKey;
292 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsAmperageKey;
293 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsDescriptionKey;
294 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsPMUConfigurationKey;
295 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSourceIDKey;
296 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsErrorFlagsKey;
297 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSharedSourceKey;
298 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsCloakedKey;
299 static OSSharedPtr<const OSSymbol> gIOPMPSInvalidWakeSecondsKey;
300 static OSSharedPtr<const OSSymbol> gIOPMPSPostChargeWaitSecondsKey;
301 static OSSharedPtr<const OSSymbol> gIOPMPSPostDishargeWaitSecondsKey;
302
303 #define kIOSleepSupportedKey "IOSleepSupported"
304 #define kIOPMSystemCapabilitiesKey "System Capabilities"
305 #define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
306
307 #define kIORequestWranglerIdleKey "IORequestIdle"
308 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
309
310 #define kIOSleepWakeFailureString "SleepWakeFailureString"
311 #define kIOEFIBootRomFailureKey "wake-failure"
312 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic"
313
314 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
315 | kIOPMSupportedOnBatt \
316 | kIOPMSupportedOnUPS)
317
318 #define kLocalEvalClamshellCommand (1 << 15)
319 #define kIdleSleepRetryInterval (3 * 60 * 1000)
320
321 // Minimum time in milliseconds after AP wake that we allow idle timer to expire.
322 // We impose this minimum to avoid race conditions in the AP wake path where
323 // userspace clients are not able to acquire power assertions before the idle timer expires.
324 #if XNU_TARGET_OS_IOS
325 #define kMinimumTimeBeforeIdleSleep 3000
326 #else
327 #define kMinimumTimeBeforeIdleSleep 1000
328 #endif
329
330 #define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID)
331
332 enum {
333 kWranglerPowerStateMin = 0,
334 kWranglerPowerStateSleep = 2,
335 kWranglerPowerStateDim = 3,
336 kWranglerPowerStateMax = 4
337 };
338
339 const char *
getPowerStateString(uint32_t state)340 getPowerStateString( uint32_t state )
341 {
342 #define POWER_STATE(x) {(uint32_t) x, #x}
343
344 static const IONamedValue powerStates[] = {
345 POWER_STATE( OFF_STATE ),
346 POWER_STATE( RESTART_STATE ),
347 POWER_STATE( SLEEP_STATE ),
348 POWER_STATE( AOT_STATE ),
349 POWER_STATE( ON_STATE ),
350 { 0, NULL }
351 };
352 return IOFindNameForValue(state, powerStates);
353 }
354
355 #define ON_POWER kIOPMPowerOn
356 #define RESTART_POWER kIOPMRestart
357 #define SLEEP_POWER kIOPMAuxPowerOn
358
359 static IOPMPowerState
360 ourPowerStates[NUM_POWER_STATES] =
361 {
362 { .version = 1,
363 .capabilityFlags = 0,
364 .outputPowerCharacter = 0,
365 .inputPowerRequirement = 0 },
366 { .version = 1,
367 .capabilityFlags = kIOPMRestartCapability,
368 .outputPowerCharacter = kIOPMRestart,
369 .inputPowerRequirement = RESTART_POWER },
370 { .version = 1,
371 .capabilityFlags = kIOPMSleepCapability,
372 .outputPowerCharacter = kIOPMSleep,
373 .inputPowerRequirement = SLEEP_POWER },
374 { .version = 1,
375 .capabilityFlags = kIOPMAOTCapability,
376 .outputPowerCharacter = kIOPMAOTPower,
377 .inputPowerRequirement = ON_POWER },
378 { .version = 1,
379 .capabilityFlags = kIOPMPowerOn,
380 .outputPowerCharacter = kIOPMPowerOn,
381 .inputPowerRequirement = ON_POWER },
382 };
383
384 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
385 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
386 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
387 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
388 #define kIOPMRootDomainWakeTypeUser "User"
389 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
390 #define kIOPMRootDomainWakeTypeNetwork "Network"
391 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
392 #define kIOPMRootDomainWakeTypeNotification "Notification"
393 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
394
395 // Special interest that entitles the interested client from receiving
396 // all system messages. Only used by powerd.
397 //
398 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
399
400 // Entitlement required for root domain clients
401 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
402
403 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
404 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
405
406 /*
407 * Aggressiveness
408 */
409 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
410 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
411
412 #define kAggressivesMinValue 1
413
414 const char *
getAggressivenessTypeString(uint32_t type)415 getAggressivenessTypeString( uint32_t type )
416 {
417 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
418
419 static const IONamedValue aggressivenessTypes[] = {
420 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ),
421 AGGRESSIVENESS_TYPE( kPMMinutesToDim ),
422 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ),
423 AGGRESSIVENESS_TYPE( kPMMinutesToSleep ),
424 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ),
425 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ),
426 AGGRESSIVENESS_TYPE( kPMPowerSource),
427 AGGRESSIVENESS_TYPE( kPMMotionSensor ),
428 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ),
429 { 0, NULL }
430 };
431 return IOFindNameForValue(type, aggressivenessTypes);
432 }
433
434 enum {
435 kAggressivesStateBusy = 0x01,
436 kAggressivesStateQuickSpindown = 0x02
437 };
438
439 struct AggressivesRecord {
440 uint32_t flags;
441 uint32_t type;
442 uint32_t value;
443 };
444
445 struct AggressivesRequest {
446 queue_chain_t chain;
447 uint32_t options;
448 uint32_t dataType;
449 union {
450 OSSharedPtr<IOService> service;
451 AggressivesRecord record;
452 } data;
453 };
454
455 enum {
456 kAggressivesRequestTypeService = 1,
457 kAggressivesRequestTypeRecord
458 };
459
460 enum {
461 kAggressivesOptionSynchronous = 0x00000001,
462 kAggressivesOptionQuickSpindownEnable = 0x00000100,
463 kAggressivesOptionQuickSpindownDisable = 0x00000200,
464 kAggressivesOptionQuickSpindownMask = 0x00000300
465 };
466
467 enum {
468 kAggressivesRecordFlagModified = 0x00000001,
469 kAggressivesRecordFlagMinValue = 0x00000002
470 };
471
472 // System Sleep Preventers
473
474 enum {
475 kPMUserDisabledAllSleep = 1,
476 kPMSystemRestartBootingInProgress,
477 kPMConfigPreventSystemSleep,
478 kPMChildPreventSystemSleep,
479 kPMCPUAssertion,
480 kPMPCIUnsupported,
481 kPMDKNotReady,
482 };
483
484 const char *
getSystemSleepPreventerString(uint32_t preventer)485 getSystemSleepPreventerString( uint32_t preventer )
486 {
487 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
488 static const IONamedValue systemSleepPreventers[] = {
489 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ),
490 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ),
491 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ),
492 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ),
493 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ),
494 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ),
495 SYSTEM_SLEEP_PREVENTER( kPMDKNotReady ),
496 { 0, NULL }
497 };
498 return IOFindNameForValue(preventer, systemSleepPreventers);
499 }
500
501 // gDarkWakeFlags
502 enum {
503 kDarkWakeFlagPromotionNone = 0x0000,
504 kDarkWakeFlagPromotionEarly = 0x0001, // promote before gfx clamp
505 kDarkWakeFlagPromotionLate = 0x0002, // promote after gfx clamp
506 kDarkWakeFlagPromotionMask = 0x0003,
507 kDarkWakeFlagAlarmIsDark = 0x0100,
508 kDarkWakeFlagAudioNotSuppressed = 0x0200,
509 kDarkWakeFlagUserWakeWorkaround = 0x1000
510 };
511
512 // gClamshellFlags
513 // The workaround for 9157444 is enabled at compile time using the
514 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below.
515 enum {
516 kClamshell_WAR_38378787 = 0x00000001,
517 kClamshell_WAR_47715679 = 0x00000002,
518 kClamshell_WAR_58009435 = 0x00000004
519 };
520
521 // acceptSystemWakeEvents()
522 enum {
523 kAcceptSystemWakeEvents_Disable = 0,
524 kAcceptSystemWakeEvents_Enable,
525 kAcceptSystemWakeEvents_Reenable
526 };
527
528 static IOPMrootDomain * gRootDomain;
529 static IORootParent * gPatriarch;
530 static IONotifier * gSysPowerDownNotifier = NULL;
531 static UInt32 gSleepOrShutdownPending = 0;
532 static UInt32 gWillShutdown = 0;
533 static UInt32 gPagingOff = 0;
534 static UInt32 gSleepWakeUUIDIsSet = false;
535 static uint32_t gAggressivesState = 0;
536 uint32_t gHaltTimeMaxLog;
537 uint32_t gHaltTimeMaxPanic;
538 IOLock * gHaltLogLock;
539 static char * gHaltLog;
540 enum { kHaltLogSize = 2048 };
541 static size_t gHaltLogPos;
542 static uint64_t gHaltStartTime;
543 static char gKextNameBuf[64];
544 static size_t gKextNamePos;
545 static bool gKextNameEnd;
546
547 uuid_string_t bootsessionuuid_string;
548
549 #if defined(XNU_TARGET_OS_OSX)
550 #if DISPLAY_WRANGLER_PRESENT
551 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionNone;
552 #elif defined(__arm64__)
553 // Enable temporary full wake promotion workarounds
554 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
555 #else
556 // Enable full wake promotion workarounds
557 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
558 #endif
559 #else /* !defined(XNU_TARGET_OS_OSX) */
560 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionEarly;
561 #endif /* !defined(XNU_TARGET_OS_OSX) */
562
563 static uint32_t gNoIdleFlag = 0;
564 static uint32_t gSleepDisabledFlag = 0;
565 static uint32_t gSwdPanic = 1;
566 static uint32_t gSwdSleepTimeout = 0;
567 static uint32_t gSwdWakeTimeout = 0;
568 static uint32_t gSwdSleepWakeTimeout = 0;
569 static PMStatsStruct gPMStats;
570 #if DEVELOPMENT || DEBUG
571 static uint32_t swd_panic_phase;
572 #endif
573
574 static uint32_t gClamshellFlags = 0
575 #if defined(__i386__) || defined(__x86_64__)
576 | kClamshell_WAR_58009435
577 #endif
578 ;
579
580 #if HIBERNATION
581
582 #if defined(__arm64__)
583 static IOReturn
defaultSleepPolicyHandler(void * ctx,const IOPMSystemSleepPolicyVariables * vars,IOPMSystemSleepParameters * params)584 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params)
585 {
586 uint32_t sleepType = kIOPMSleepTypeDeepIdle;
587
588 assert(vars->signature == kIOPMSystemSleepPolicySignature);
589 assert(vars->version == kIOPMSystemSleepPolicyVersion);
590
591 // Hibernation enabled and either user forced hibernate or low battery sleep
592 if ((vars->hibernateMode & kIOHibernateModeOn) &&
593 (((vars->hibernateMode & kIOHibernateModeSleep) == 0) ||
594 (vars->sleepFactors & kIOPMSleepFactorBatteryLow))) {
595 sleepType = kIOPMSleepTypeHibernate;
596 }
597 params->version = kIOPMSystemSleepParametersVersion;
598 params->sleepType = sleepType;
599 return kIOReturnSuccess;
600 }
601 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = &defaultSleepPolicyHandler;
602 #else /* defined(__arm64__) */
603 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = NULL;
604 #endif /* defined(__arm64__) */
605
606 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
607 static void * gSleepPolicyTarget;
608 #endif
609
610 struct timeval gIOLastSleepTime;
611 struct timeval gIOLastWakeTime;
612 AbsoluteTime gIOLastWakeAbsTime;
613 AbsoluteTime gIOLastSleepAbsTime;
614
615 struct timeval gIOLastUserSleepTime;
616
617 static char gWakeReasonString[128];
618 static char gBootReasonString[80];
619 static char gShutdownReasonString[80];
620 static uint64_t gShutdownTime;
621 static bool gWakeReasonSysctlRegistered = false;
622 static bool gBootReasonSysctlRegistered = false;
623 static bool gShutdownReasonSysctlRegistered = false;
624 static bool gWillShutdownSysctlRegistered = false;
625 static AbsoluteTime gUserActiveAbsTime;
626 static AbsoluteTime gUserInactiveAbsTime;
627
628 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
629 static bool gSpinDumpBufferFull = false;
630 #endif
631
632 z_stream swd_zs;
633 vm_offset_t swd_zs_zmem;
634 //size_t swd_zs_zsize;
635 size_t swd_zs_zoffset;
636 #if defined(__i386__) || defined(__x86_64__)
637 IOCPU *currentShutdownTarget = NULL;
638 #endif
639
640 static unsigned int gPMHaltBusyCount;
641 static unsigned int gPMHaltIdleCount;
642 static int gPMHaltDepth;
643 static uint32_t gPMHaltMessageType;
644 static IOLock * gPMHaltLock = NULL;
645 static OSSharedPtr<OSArray> gPMHaltArray;
646 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey;
647 static bool gPMQuiesced;
648
649 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
650 #define kCPUUnknownIndex 9999999
651 enum {
652 kInformAC = 0,
653 kInformLid = 1,
654 kInformableCount = 2
655 };
656
657 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut;
658 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel;
659 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow;
660 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt;
661 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow;
662
663 #define kBadPMFeatureID 0
664
665 /*
666 * PMSettingHandle
667 * Opaque handle passed to clients of registerPMSettingController()
668 */
669 class PMSettingHandle : public OSObject
670 {
671 OSDeclareFinalStructors( PMSettingHandle );
672 friend class PMSettingObject;
673
674 private:
675 PMSettingObject *pmso;
676 void free(void) APPLE_KEXT_OVERRIDE;
677 };
678
679 /*
680 * PMSettingObject
681 * Internal object to track each PM setting controller
682 */
683 class PMSettingObject : public OSObject
684 {
685 OSDeclareFinalStructors( PMSettingObject );
686 friend class IOPMrootDomain;
687
688 private:
689 queue_head_t calloutQueue;
690 thread_t waitThread;
691 IOPMrootDomain *parent;
692 PMSettingHandle *pmsh;
693 IOPMSettingControllerCallback func;
694 OSObject *target;
695 uintptr_t refcon;
696 OSDataAllocation<uint32_t> publishedFeatureID;
697 uint32_t settingCount;
698 bool disabled;
699
700 void free(void) APPLE_KEXT_OVERRIDE;
701
702 public:
703 static PMSettingObject *pmSettingObject(
704 IOPMrootDomain *parent_arg,
705 IOPMSettingControllerCallback handler_arg,
706 OSObject *target_arg,
707 uintptr_t refcon_arg,
708 uint32_t supportedPowerSources,
709 const OSSymbol *settings[],
710 OSObject **handle_obj);
711
712 IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
713 void clientHandleFreed(void);
714 };
715
716 struct PMSettingCallEntry {
717 queue_chain_t link;
718 thread_t thread;
719 };
720
721 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
722 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
723 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
724 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
725
726 /*
727 * PMTraceWorker
728 * Internal helper object for logging trace points to RTC
729 * IOPMrootDomain and only IOPMrootDomain should instantiate
730 * exactly one of these.
731 */
732
733 typedef void (*IOPMTracePointHandler)(
734 void * target, uint32_t code, uint32_t data );
735
736 class PMTraceWorker : public OSObject
737 {
738 OSDeclareDefaultStructors(PMTraceWorker);
739 public:
740 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
741
742 static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * );
743 void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
744 void tracePoint(uint8_t phase);
745 void traceDetail(uint32_t detail);
746 void traceComponentWakeProgress(uint32_t component, uint32_t data);
747 int recordTopLevelPCIDevice(IOService *);
748 void RTC_TRACE(void);
749 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
750
751 IOPMTracePointHandler tracePointHandler;
752 void * tracePointTarget;
753 uint64_t getPMStatusCode();
754 uint8_t getTracePhase();
755 uint32_t getTraceData();
756 private:
757 IOPMrootDomain *owner;
758 IOLock *pmTraceWorkerLock;
759 OSSharedPtr<OSArray> pciDeviceBitMappings;
760
761 uint8_t addedToRegistry;
762 uint8_t tracePhase;
763 uint32_t traceData32;
764 uint8_t loginWindowData;
765 uint8_t coreDisplayData;
766 uint8_t coreGraphicsData;
767 };
768
769 /*
770 * this should be treated as POD, as it's byte-copied around
771 * and we cannot rely on d'tor firing at the right time
772 */
773 struct PMAssertStruct {
774 IOPMDriverAssertionID id;
775 IOPMDriverAssertionType assertionBits;
776 uint64_t createdTime;
777 uint64_t modifiedTime;
778 const OSSymbol *ownerString;
779 IOService *ownerService;
780 uint64_t registryEntryID;
781 IOPMDriverAssertionLevel level;
782 uint64_t assertCPUStartTime;
783 uint64_t assertCPUDuration;
784 };
785 OSDefineValueObjectForDependentType(PMAssertStruct)
786
787 /*
788 * PMAssertionsTracker
789 * Tracks kernel and user space PM assertions
790 */
791 class PMAssertionsTracker : public OSObject
792 {
793 OSDeclareFinalStructors(PMAssertionsTracker);
794 public:
795 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * );
796
797 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
798 IOReturn releaseAssertion(IOPMDriverAssertionID);
799 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
800 IOReturn setUserAssertionLevels(IOPMDriverAssertionType);
801
802 OSSharedPtr<OSArray> copyAssertionsArray(void);
803 IOPMDriverAssertionType getActivatedAssertions(void);
804 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType);
805
806 IOReturn handleCreateAssertion(OSValueObject<PMAssertStruct> *);
807 IOReturn handleReleaseAssertion(IOPMDriverAssertionID);
808 IOReturn handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
809 IOReturn handleSetUserAssertionLevels(void * arg0);
810 void publishProperties(void);
811 void reportCPUBitAccounting(void);
812 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *);
813
814 private:
815 uint32_t tabulateProducerCount;
816 uint32_t tabulateConsumerCount;
817
818 uint64_t maxAssertCPUDuration;
819 uint64_t maxAssertCPUEntryId;
820
821 void tabulate(void);
822 void updateCPUBitAccounting(PMAssertStruct * assertStruct);
823
824 IOPMrootDomain *owner;
825 OSSharedPtr<OSArray> assertionsArray;
826 IOLock *assertionsArrayLock;
827 IOPMDriverAssertionID issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
828 IOPMDriverAssertionType assertionsKernel;
829 IOPMDriverAssertionType assertionsUser;
830 IOPMDriverAssertionType assertionsCombined;
831 };
832
833 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
834
835 /*
836 * PMHaltWorker
837 * Internal helper object for Shutdown/Restart notifications.
838 */
839 #define kPMHaltMaxWorkers 8
840 #define kPMHaltTimeoutMS 100
841
842 class PMHaltWorker : public OSObject
843 {
844 OSDeclareFinalStructors( PMHaltWorker );
845
846 public:
847 IOService * service;// service being worked on
848 AbsoluteTime startTime; // time when work started
849 int depth; // work on nubs at this PM-tree depth
850 int visits; // number of nodes visited (debug)
851 IOLock * lock;
852 bool timeout;// service took too long
853
854 static PMHaltWorker * worker( void );
855 static void main( void * arg, wait_result_t waitResult );
856 static void work( PMHaltWorker * me );
857 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
858 virtual void free( void ) APPLE_KEXT_OVERRIDE;
859 };
860
OSDefineMetaClassAndFinalStructors(PMHaltWorker,OSObject)861 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
862
863
864 #define super IOService
865 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
866
867 boolean_t
868 IOPMRootDomainGetWillShutdown(void)
869 {
870 return gWillShutdown != 0;
871 }
872
873 static void
IOPMRootDomainWillShutdown(void)874 IOPMRootDomainWillShutdown(void)
875 {
876 if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
877 IOService::willShutdown();
878 for (int i = 0; i < 100; i++) {
879 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
880 break;
881 }
882 IOSleep( 100 );
883 }
884 }
885 }
886
887 extern "C" IONotifier *
registerSleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)888 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
889 {
890 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
891 }
892
893 extern "C" IONotifier *
registerPrioritySleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)894 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
895 {
896 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
897 }
898
899 extern "C" IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon)900 acknowledgeSleepWakeNotification(void * PMrefcon)
901 {
902 return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
903 }
904
905 extern "C" IOReturn
vetoSleepWakeNotification(void * PMrefcon)906 vetoSleepWakeNotification(void * PMrefcon)
907 {
908 return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
909 }
910
911 extern "C" IOReturn
rootDomainRestart(void)912 rootDomainRestart( void )
913 {
914 return gRootDomain->restartSystem();
915 }
916
917 extern "C" IOReturn
rootDomainShutdown(void)918 rootDomainShutdown( void )
919 {
920 return gRootDomain->shutdownSystem();
921 }
922
923 static void
halt_log_putc(char c)924 halt_log_putc(char c)
925 {
926 if (gHaltLogPos >= (kHaltLogSize - 2)) {
927 return;
928 }
929 gHaltLog[gHaltLogPos++] = c;
930 }
931
932 extern "C" void
933 _doprnt_log(const char *fmt,
934 va_list *argp,
935 void (*putc)(char),
936 int radix);
937
938 static int
halt_log(const char * fmt,...)939 halt_log(const char *fmt, ...)
940 {
941 va_list listp;
942
943 va_start(listp, fmt);
944 _doprnt_log(fmt, &listp, &halt_log_putc, 16);
945 va_end(listp);
946
947 return 0;
948 }
949
950 extern "C" void
halt_log_enter(const char * what,const void * pc,uint64_t time)951 halt_log_enter(const char * what, const void * pc, uint64_t time)
952 {
953 uint64_t nano, millis;
954
955 if (!gHaltLog) {
956 return;
957 }
958 absolutetime_to_nanoseconds(time, &nano);
959 millis = nano / NSEC_PER_MSEC;
960 if (millis < 100) {
961 return;
962 }
963
964 IOLockLock(gHaltLogLock);
965 if (pc) {
966 halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
967 OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
968 OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
969 } else {
970 halt_log("%s: %qd ms\n", what, millis);
971 }
972
973 gHaltLog[gHaltLogPos] = 0;
974 IOLockUnlock(gHaltLogLock);
975 }
976
977 extern uint32_t gFSState;
978
979 extern "C" void
IOSystemShutdownNotification(int howto,int stage)980 IOSystemShutdownNotification(int howto, int stage)
981 {
982 uint64_t startTime;
983
984 if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
985 #if defined(XNU_TARGET_OS_OSX)
986 uint64_t nano, millis;
987 startTime = mach_absolute_time();
988 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
989 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
990 millis = nano / NSEC_PER_MSEC;
991 if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
992 printf("waitQuiet() for unmount %qd ms\n", millis);
993 }
994 #endif /* defined(XNU_TARGET_OS_OSX) */
995 return;
996 }
997
998 if (kIOSystemShutdownNotificationTerminateDEXTs == stage) {
999 uint64_t nano, millis;
1000 startTime = mach_absolute_time();
1001 IOServicePH::systemHalt(howto);
1002 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
1003 millis = nano / NSEC_PER_MSEC;
1004 if (true || (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog))) {
1005 printf("IOServicePH::systemHalt took %qd ms\n", millis);
1006 }
1007 return;
1008 }
1009
1010 assert(kIOSystemShutdownNotificationStageProcessExit == stage);
1011
1012 IOLockLock(gHaltLogLock);
1013 if (!gHaltLog) {
1014 gHaltLog = IONewData(char, (vm_size_t)kHaltLogSize);
1015 gHaltStartTime = mach_absolute_time();
1016 if (gHaltLog) {
1017 halt_log_putc('\n');
1018 }
1019 }
1020 IOLockUnlock(gHaltLogLock);
1021
1022 startTime = mach_absolute_time();
1023 IOPMRootDomainWillShutdown();
1024 halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
1025 #if HIBERNATION
1026 startTime = mach_absolute_time();
1027 IOHibernateSystemPostWake(true);
1028 halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
1029 #endif
1030 if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1031 gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1032 }
1033 }
1034
1035 extern "C" int sync_internal(void);
1036
1037 /*
1038 * A device is always in the highest power state which satisfies its driver,
1039 * its policy-maker, and any power children it has, but within the constraint
1040 * of the power state provided by its parent. The driver expresses its desire by
1041 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
1042 * changePowerStateToPriv(), and the children express their desires by calling
1043 * requestPowerDomainState().
1044 *
1045 * The Root Power Domain owns the policy for idle and demand sleep for the system.
1046 * It is a power-managed IOService just like the others in the system.
1047 * It implements several power states which map to what we see as Sleep and On.
1048 *
1049 * The sleep policy is as follows:
1050 * 1. Sleep is prevented if the case is open so that nobody will think the machine
1051 * is off and plug/unplug cards.
1052 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1053 * 3. System cannot Sleep if some object in the tree is in a power state marked
1054 * kIOPMPreventSystemSleep.
1055 *
1056 * These three conditions are enforced using the "driver clamp" by calling
1057 * changePowerStateTo(). For example, if the case is opened,
1058 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
1059 * of the desires of the children of the root or the state of the other clamp.
1060 *
1061 * Demand Sleep is initiated by pressing the front panel power button, closing
1062 * the clamshell, or selecting the menu item. In this case the root's parent
1063 * actually initiates the power state change so that the root domain has no
1064 * choice and does not give applications the opportunity to veto the change.
1065 *
1066 * Idle Sleep occurs if no objects in the tree are in a state marked
1067 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
1068 * the root on, so it sets the "policy-maker clamp" by calling
1069 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1070 * This timer is set for the difference between the sleep timeout slider and the
1071 * display dim timeout slider. When the timer expires, it releases its clamp and
1072 * now nothing is holding it awake, so it falls asleep.
1073 *
1074 * Demand sleep is prevented when the system is booting. When preferences are
1075 * transmitted by the loginwindow at the end of boot, a flag is cleared,
1076 * and this allows subsequent Demand Sleep.
1077 */
1078
1079 //******************************************************************************
1080
1081 IOPMrootDomain *
construct(void)1082 IOPMrootDomain::construct( void )
1083 {
1084 IOPMrootDomain *root;
1085
1086 root = new IOPMrootDomain;
1087 if (root) {
1088 root->init();
1089 }
1090
1091 return root;
1092 }
1093
1094 //******************************************************************************
1095 // updateConsoleUsersCallout
1096 //
1097 //******************************************************************************
1098
1099 static void
updateConsoleUsersCallout(thread_call_param_t p0,thread_call_param_t p1)1100 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1101 {
1102 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1103 rootDomain->updateConsoleUsers();
1104 }
1105
1106 void
updateConsoleUsers(void)1107 IOPMrootDomain::updateConsoleUsers(void)
1108 {
1109 IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1110 updateTasksSuspend(kTasksSuspendUnsuspended, kTasksSuspendNoChange);
1111 }
1112
1113 bool
updateTasksSuspend(int newTasksSuspended,int newAOTTasksSuspended)1114 IOPMrootDomain::updateTasksSuspend(int newTasksSuspended, int newAOTTasksSuspended)
1115 {
1116 bool newSuspend;
1117
1118 WAKEEVENT_LOCK();
1119 if (newTasksSuspended != kTasksSuspendNoChange) {
1120 tasksSuspended = (newTasksSuspended != kTasksSuspendUnsuspended);
1121 }
1122 if (newAOTTasksSuspended != kTasksSuspendNoChange) {
1123 _aotTasksSuspended = (newAOTTasksSuspended != kTasksSuspendUnsuspended);
1124 }
1125 newSuspend = (tasksSuspended || _aotTasksSuspended);
1126 if (newSuspend == tasksSuspendState) {
1127 WAKEEVENT_UNLOCK();
1128 return false;
1129 }
1130 tasksSuspendState = newSuspend;
1131 WAKEEVENT_UNLOCK();
1132 tasks_system_suspend(newSuspend);
1133 return true;
1134 }
1135
1136 //******************************************************************************
1137
1138 static void
disk_sync_callout(thread_call_param_t p0,thread_call_param_t p1)1139 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1140 {
1141 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1142 uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
1143 uint32_t powerState = rootDomain->getPowerState();
1144
1145 DLOG("disk_sync_callout ps=%u\n", powerState);
1146
1147 if (ON_STATE == powerState) {
1148 sync_internal();
1149
1150 #if HIBERNATION
1151 // Block sleep until trim issued on previous wake path is completed.
1152 IOHibernateSystemPostWake(true);
1153 #endif
1154 }
1155 #if HIBERNATION
1156 else {
1157 IOHibernateSystemPostWake(false);
1158
1159 rootDomain->sleepWakeDebugSaveSpinDumpFile();
1160 }
1161 #endif
1162
1163 rootDomain->allowPowerChange(notifyRef);
1164 DLOG("disk_sync_callout finish\n");
1165 }
1166
1167 //******************************************************************************
1168 static UInt32
computeDeltaTimeMS(const AbsoluteTime * startTime,AbsoluteTime * elapsedTime)1169 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1170 {
1171 AbsoluteTime endTime;
1172 UInt64 nano = 0;
1173
1174 clock_get_uptime(&endTime);
1175 if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1176 *elapsedTime = 0;
1177 } else {
1178 SUB_ABSOLUTETIME(&endTime, startTime);
1179 absolutetime_to_nanoseconds(endTime, &nano);
1180 *elapsedTime = endTime;
1181 }
1182
1183 return (UInt32)(nano / NSEC_PER_MSEC);
1184 }
1185
1186 //******************************************************************************
1187
1188 static int
1189 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1190 {
1191 struct timeval *swt = (struct timeval *)arg1;
1192 struct proc *p = req->p;
1193
1194 if (p == kernproc) {
1195 return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
1196 } else if (proc_is64bit(p)) {
1197 struct user64_timeval t = {};
1198 t.tv_sec = swt->tv_sec;
1199 t.tv_usec = swt->tv_usec;
1200 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1201 } else {
1202 struct user32_timeval t = {};
1203 t.tv_sec = (typeof(t.tv_sec))swt->tv_sec;
1204 t.tv_usec = swt->tv_usec;
1205 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1206 }
1207 }
1208
1209 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1210 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1211 &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1212
1213 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1214 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1215 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1216
1217 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
1218 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
1219 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
1220 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
1221
1222 static int
1223 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1224 {
1225 int new_value, changed, error;
1226
1227 if (!gWillShutdownSysctlRegistered) {
1228 return ENOENT;
1229 }
1230
1231 error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1232 if (changed) {
1233 if (!gWillShutdown && (new_value == 1)) {
1234 IOPMRootDomainWillShutdown();
1235 } else {
1236 error = EINVAL;
1237 }
1238 }
1239 return error;
1240 }
1241
1242 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1243 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1244 NULL, 0, sysctl_willshutdown, "I", "");
1245
1246 #if defined(XNU_TARGET_OS_OSX)
1247
1248 static int
sysctl_progressmeterenable(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1249 sysctl_progressmeterenable
1250 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1251 {
1252 int error;
1253 int new_value, changed;
1254
1255 error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1256
1257 if (changed) {
1258 vc_enable_progressmeter(new_value);
1259 }
1260
1261 return error;
1262 }
1263
1264 static int
sysctl_progressmeter(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1265 sysctl_progressmeter
1266 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1267 {
1268 int error;
1269 int new_value, changed;
1270
1271 error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1272
1273 if (changed) {
1274 vc_set_progressmeter(new_value);
1275 }
1276
1277 return error;
1278 }
1279
1280 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1281 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1282 NULL, 0, sysctl_progressmeterenable, "I", "");
1283
1284 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1285 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1286 NULL, 0, sysctl_progressmeter, "I", "");
1287
1288 #endif /* defined(XNU_TARGET_OS_OSX) */
1289
1290
1291
1292 static int
sysctl_consoleoptions(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1293 sysctl_consoleoptions
1294 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1295 {
1296 int error, changed;
1297 uint32_t new_value;
1298
1299 error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1300
1301 if (changed) {
1302 vc_user_options.options = new_value;
1303 }
1304
1305 return error;
1306 }
1307
1308 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1309 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1310 NULL, 0, sysctl_consoleoptions, "I", "");
1311
1312
1313 static int
1314 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1315 {
1316 return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1317 }
1318
1319 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1320 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1321 NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1322
1323
1324 static int
1325 sysctl_wakereason SYSCTL_HANDLER_ARGS
1326 {
1327 char wr[sizeof(gWakeReasonString)];
1328
1329 wr[0] = '\0';
1330 if (gRootDomain && gWakeReasonSysctlRegistered) {
1331 gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1332 } else {
1333 return ENOENT;
1334 }
1335
1336 return sysctl_io_string(req, wr, 0, 0, NULL);
1337 }
1338
1339 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1340 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1341 NULL, 0, sysctl_wakereason, "A", "wakereason");
1342
1343 static int
1344 sysctl_bootreason SYSCTL_HANDLER_ARGS
1345 {
1346 if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) {
1347 return ENOENT;
1348 }
1349
1350 return sysctl_io_string(req, gBootReasonString, 0, 0, NULL);
1351 }
1352
1353 SYSCTL_PROC(_kern, OID_AUTO, bootreason,
1354 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1355 NULL, 0, sysctl_bootreason, "A", "");
1356
1357 static int
1358 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1359 {
1360 char sr[sizeof(gShutdownReasonString)];
1361
1362 sr[0] = '\0';
1363 if (gRootDomain && gShutdownReasonSysctlRegistered) {
1364 gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1365 } else {
1366 return ENOENT;
1367 }
1368
1369 return sysctl_io_string(req, sr, 0, 0, NULL);
1370 }
1371
1372 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1373 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1374 NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1375
1376 // This value is meant to represent the last time the device shut down
1377 // in a unit of the PMU driver's choosing see rdar://138590268 for details
1378 static int
1379 sysctl_shutdowntime SYSCTL_HANDLER_ARGS
1380 {
1381 uint64_t shutdownTime = 0;
1382
1383 if (gRootDomain && gShutdownReasonSysctlRegistered) {
1384 gRootDomain->copyShutdownTime(&shutdownTime);
1385 } else {
1386 return ENOENT;
1387 }
1388
1389 return SYSCTL_OUT(req, &shutdownTime, sizeof(shutdownTime));
1390 }
1391
1392 SYSCTL_PROC(_kern, OID_AUTO, shutdowntime,
1393 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1394 NULL, 0, sysctl_shutdowntime, "Q", "shutdowntime");
1395
1396 static int
1397 sysctl_targettype SYSCTL_HANDLER_ARGS
1398 {
1399 IOService * root;
1400 OSSharedPtr<OSObject> obj;
1401 OSData * data;
1402 char tt[32];
1403
1404 tt[0] = '\0';
1405 root = IOService::getServiceRoot();
1406 if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1407 if ((data = OSDynamicCast(OSData, obj.get()))) {
1408 strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1409 }
1410 }
1411 return sysctl_io_string(req, tt, 0, 0, NULL);
1412 }
1413
1414 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1415 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1416 NULL, 0, sysctl_targettype, "A", "targettype");
1417
1418 static SECURITY_READ_ONLY_LATE(char*) jetsam_properties_product_type_string = NULL;
1419 static SECURITY_READ_ONLY_LATE(size_t) jetsam_properties_product_type_string_len = 0;
1420
1421 /*
1422 * SecureDTLookupEntry() is only guaranteed to work before PE_init_iokit(),
1423 * so we load the jetsam_properties_product_type string (if available) in a startup handler.
1424 */
1425 __startup_func
1426 static void
sysctl_load_jetsam_properties_product_type(void)1427 sysctl_load_jetsam_properties_product_type(void)
1428 {
1429 DTEntry node;
1430 void const *value = NULL;
1431 unsigned int size = 0;
1432
1433 if (kSuccess != SecureDTLookupEntry(nullptr, "/product", &node)) {
1434 return;
1435 }
1436
1437 if (kSuccess != SecureDTGetProperty(node, "jetsam-properties-product-type", (void const **) &value, &size)) {
1438 return;
1439 }
1440
1441 if (size == 0) {
1442 return;
1443 }
1444
1445 jetsam_properties_product_type_string = (char *) zalloc_permanent(size, ZALIGN_NONE);
1446 if (jetsam_properties_product_type_string == NULL) {
1447 return;
1448 }
1449
1450 memcpy(jetsam_properties_product_type_string, value, size);
1451 jetsam_properties_product_type_string_len = size;
1452 }
1453 STARTUP(SYSCTL, STARTUP_RANK_MIDDLE, sysctl_load_jetsam_properties_product_type);
1454
1455 static int
1456 sysctl_jetsam_properties_product_type SYSCTL_HANDLER_ARGS
1457 {
1458 if (jetsam_properties_product_type_string != NULL) {
1459 return SYSCTL_OUT(req, jetsam_properties_product_type_string, jetsam_properties_product_type_string_len);
1460 }
1461
1462 IOService * root;
1463 OSSharedPtr<OSObject> obj;
1464 OSData * data;
1465 char tt[32];
1466
1467 tt[0] = '\0';
1468 root = IOService::getServiceRoot();
1469 if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1470 if ((data = OSDynamicCast(OSData, obj.get()))) {
1471 strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1472 }
1473 }
1474 return sysctl_io_string(req, tt, 0, 0, NULL);
1475 }
1476
1477 SYSCTL_PROC(_hw, OID_AUTO, jetsam_properties_product_type,
1478 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1479 NULL, 0, sysctl_jetsam_properties_product_type, "A", "jetsam_properties_product_type");
1480
1481 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1482 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1483 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1484 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1485 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1486 #if DEVELOPMENT || DEBUG
1487 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
1488 #if defined(XNU_TARGET_OS_OSX)
1489 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, "");
1490 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1491 #endif /* defined(XNU_TARGET_OS_OSX) */
1492 #endif /* DEVELOPMENT || DEBUG */
1493
1494 //******************************************************************************
1495 // AOT
1496
1497 static int
1498 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1499 {
1500 if (NULL == gRootDomain) {
1501 return ENOENT;
1502 }
1503 if (NULL == gRootDomain->_aotMetrics) {
1504 IOPMAOTMetrics nullMetrics = {};
1505 return sysctl_io_opaque(req, &nullMetrics, sizeof(IOPMAOTMetrics), NULL);
1506 }
1507 return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1508 }
1509
1510 TUNABLE_DT_WRITEABLE(uint32_t, gAOTMode, "/product/iopm",
1511 "aot-mode", "aot_mode", 0, TUNABLE_DT_NONE);
1512 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
1513 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1514 NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
1515
1516
1517 static int
update_aotmode(uint32_t mode)1518 update_aotmode(uint32_t mode)
1519 {
1520 int result;
1521
1522 if (!gIOPMWorkLoop) {
1523 return ENOENT;
1524 }
1525 result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1526 unsigned int oldCount;
1527
1528 if (mode && !gRootDomain->_aotMetrics) {
1529 gRootDomain->_aotMetrics = IOMallocType(IOPMAOTMetrics);
1530 }
1531
1532 oldCount = gRootDomain->idleSleepPreventersCount();
1533 gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1534 gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1535 return 0;
1536 });
1537 return result;
1538 }
1539
1540 static int
sysctl_aotmodebits(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1541 sysctl_aotmodebits
1542 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1543 {
1544 int error, changed;
1545 uint32_t new_value;
1546
1547 if (NULL == gRootDomain) {
1548 return ENOENT;
1549 }
1550 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1551 if (changed && gIOPMWorkLoop) {
1552 error = update_aotmode(new_value);
1553 }
1554
1555 return error;
1556 }
1557
1558 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1559 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1560 NULL, 0, sysctl_aotmodebits, "I", "");
1561
1562 static int
sysctl_aotmode(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1563 sysctl_aotmode
1564 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1565 {
1566 int error, changed;
1567 uint32_t new_value;
1568
1569 if (NULL == gRootDomain) {
1570 return ENOENT;
1571 }
1572 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1573 if (changed && gIOPMWorkLoop) {
1574 if (new_value) {
1575 new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1576 }
1577 error = update_aotmode(new_value);
1578 }
1579
1580 return error;
1581 }
1582
1583 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
1584 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1585 NULL, 0, sysctl_aotmode, "I", "");
1586
1587 TUNABLE_DT(uint32_t, gAOTLingerTimeMS, "/product/iopm",
1588 "aot-linger-time-ms", "aot_linger_time_ms", 800, TUNABLE_DT_NONE);
1589
1590 // Low Power Wake tunables
1591 TUNABLE_DT_WRITEABLE(uint64_t, gLPWFlags, "/product/iopm",
1592 "low-power-wake", "low_power_wake", false, TUNABLE_DT_NONE);
1593 static SYSCTL_QUAD(_kern, OID_AUTO, lowpowerwake, CTLFLAG_RW | CTLFLAG_LOCKED,
1594 &gLPWFlags, "Low Power Wake");
1595
1596 //******************************************************************************
1597
1598 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey;
1599 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey;
1600 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey;
1601 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey;
1602 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey;
1603 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey;
1604 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey;
1605 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey;
1606 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey;
1607 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey;
1608 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey;
1609 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey;
1610
1611 //******************************************************************************
1612 // start
1613 //
1614 //******************************************************************************
1615
1616 #define kRootDomainSettingsCount 20
1617 #define kRootDomainNoPublishSettingsCount 4
1618
1619 bool
start(IOService * nub)1620 IOPMrootDomain::start( IOService * nub )
1621 {
1622 OSSharedPtr<OSIterator> psIterator;
1623 OSSharedPtr<OSDictionary> tmpDict;
1624
1625 super::start(nub);
1626
1627 gRootDomain = this;
1628 gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1629 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1630 gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
1631 gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
1632 gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1633 gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
1634 gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1635 gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1636 gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1637 gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1638 gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1639 gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey);
1640
1641 gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1642 gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1643 gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1644 gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1645 gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1646
1647 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1648 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1649 gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1650
1651 OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1652 {
1653 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1654 gIOPMSettingAutoWakeSecondsKey,
1655 gIOPMSettingAutoPowerSecondsKey,
1656 gIOPMSettingAutoWakeCalendarKey,
1657 gIOPMSettingAutoPowerCalendarKey,
1658 gIOPMSettingDebugWakeRelativeKey,
1659 gIOPMSettingDebugPowerRelativeKey,
1660 OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1661 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1662 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1663 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1664 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1665 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1666 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1667 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1668 OSSymbol::withCString(kIOPMStateConsoleShutdown),
1669 OSSymbol::withCString(kIOPMSettingProModeControl),
1670 OSSymbol::withCString(kIOPMSettingProModeDefer),
1671 gIOPMSettingSilentRunningKey,
1672 gIOPMSettingLowLatencyAudioModeKey,
1673 };
1674
1675 OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1676 {
1677 OSSymbol::withCString(kIOPMSettingProModeControl),
1678 OSSymbol::withCString(kIOPMSettingProModeDefer),
1679 gIOPMSettingSilentRunningKey,
1680 gIOPMSettingLowLatencyAudioModeKey,
1681 };
1682
1683 #if DEVELOPMENT || DEBUG
1684 #if defined(XNU_TARGET_OS_OSX)
1685 PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1686 PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags));
1687 #endif /* defined(XNU_TARGET_OS_OSX) */
1688 #endif /* DEVELOPMENT || DEBUG */
1689
1690 PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1691 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1692 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1693 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1694 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1695 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1696
1697 _aotMode = gAOTMode;
1698 _aotLingerTime = gAOTLingerTimeMS;
1699 _aotMetrics = _aotMode ? IOMallocType(IOPMAOTMetrics) : NULL;
1700
1701 // read noidle setting from Device Tree
1702 if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
1703 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
1704 }
1705
1706 queue_init(&aggressivesQueue);
1707 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1708 aggressivesData = OSData::withCapacity(
1709 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1710
1711 featuresDictLock = IOLockAlloc();
1712 settingsCtrlLock = IOLockAlloc();
1713 wakeEventLock = IOLockAlloc();
1714 gHaltLogLock = IOLockAlloc();
1715 setPMRootDomain(this);
1716
1717 extraSleepTimer = thread_call_allocate(
1718 idleSleepTimerExpired,
1719 (thread_call_param_t) this);
1720
1721 powerButtonDown = thread_call_allocate(
1722 powerButtonDownCallout,
1723 (thread_call_param_t) this);
1724
1725 powerButtonUp = thread_call_allocate(
1726 powerButtonUpCallout,
1727 (thread_call_param_t) this);
1728
1729 diskSyncCalloutEntry = thread_call_allocate(
1730 &disk_sync_callout,
1731 (thread_call_param_t) this);
1732 updateConsoleUsersEntry = thread_call_allocate(
1733 &updateConsoleUsersCallout,
1734 (thread_call_param_t) this);
1735
1736 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1737 fullWakeThreadCall = thread_call_allocate_with_options(
1738 OSMemberFunctionCast(thread_call_func_t, this,
1739 &IOPMrootDomain::fullWakeDelayedWork),
1740 (thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL,
1741 THREAD_CALL_OPTIONS_ONCE);
1742 #endif
1743
1744 setProperty(kIOSleepSupportedKey, true);
1745
1746 bzero(&gPMStats, sizeof(gPMStats));
1747
1748 pmTracer = PMTraceWorker::tracer(this);
1749
1750 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1751
1752 userDisabledAllSleep = false;
1753 systemBooting = true;
1754 idleSleepEnabled = false;
1755 idleSleepRevertible = true;
1756 sleepSlider = 0;
1757 idleSleepTimerPending = false;
1758 wrangler = NULL;
1759 clamshellClosed = false;
1760 clamshellExists = false;
1761 #if DISPLAY_WRANGLER_PRESENT
1762 clamshellDisabled = true;
1763 #else
1764 clamshellDisabled = false;
1765 #endif
1766 clamshellIgnoreClose = false;
1767 acAdaptorConnected = true;
1768 clamshellSleepDisableMask = 0;
1769 gWakeReasonString[0] = '\0';
1770
1771 // Initialize to user active.
1772 // Will never transition to user inactive w/o wrangler.
1773 fullWakeReason = kFullWakeReasonLocalUser;
1774 userIsActive = userWasActive = true;
1775 clock_get_uptime(&gUserActiveAbsTime);
1776 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
1777
1778 // Set the default system capabilities at boot.
1779 _currentCapability = kIOPMSystemCapabilityCPU |
1780 kIOPMSystemCapabilityGraphics |
1781 kIOPMSystemCapabilityAudio |
1782 kIOPMSystemCapabilityNetwork;
1783
1784 _pendingCapability = _currentCapability;
1785 _desiredCapability = _currentCapability;
1786 _highestCapability = _currentCapability;
1787 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1788
1789 queuedSleepWakeUUIDString = NULL;
1790 initializeBootSessionUUID();
1791 pmStatsAppResponses = OSArray::withCapacity(5);
1792 _statsNameKey = OSSymbol::withCString(kIOPMStatsNameKey);
1793 _statsPIDKey = OSSymbol::withCString(kIOPMStatsPIDKey);
1794 _statsTimeMSKey = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1795 _statsResponseTypeKey = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1796 _statsMessageTypeKey = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1797 _statsPowerCapsKey = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1798 assertOnWakeSecs = -1;// Invalid value to prevent updates
1799
1800 pmStatsLock = IOLockAlloc();
1801 idxPMCPUClamshell = kCPUUnknownIndex;
1802 idxPMCPULimitedPower = kCPUUnknownIndex;
1803
1804 tmpDict = OSDictionary::withCapacity(1);
1805 setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1806
1807 // Set a default "SystemPowerProfileOverrideDict" for platform
1808 // drivers without any overrides.
1809 if (!propertyExists(kIOPMSystemDefaultOverrideKey)) {
1810 tmpDict = OSDictionary::withCapacity(1);
1811 setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get());
1812 }
1813
1814 settingsCallbacks = OSDictionary::withCapacity(1);
1815
1816 // Create a list of the valid PM settings that we'll relay to
1817 // interested clients in setProperties() => setPMSetting()
1818 allowedPMSettings = OSArray::withObjects(
1819 (const OSObject **)settingsArr,
1820 kRootDomainSettingsCount,
1821 0);
1822
1823 // List of PM settings that should not automatically publish itself
1824 // as a feature when registered by a listener.
1825 noPublishPMSettings = OSArray::withObjects(
1826 (const OSObject **)noPublishSettingsArr,
1827 kRootDomainNoPublishSettingsCount,
1828 0);
1829
1830 fPMSettingsDict = OSDictionary::withCapacity(5);
1831 preventIdleSleepList = OSSet::withCapacity(8);
1832 preventSystemSleepList = OSSet::withCapacity(2);
1833
1834 PMinit(); // creates gIOPMWorkLoop
1835 gIOPMWorkLoop = getIOPMWorkloop();
1836
1837 commandGate = IOCommandGate::commandGate(gIOPMWorkLoop);
1838 gIOPMWorkLoop->addEventSource(commandGate.get());
1839
1840 // Create IOPMPowerStateQueue used to queue external power
1841 // events, and to handle those events on the PM work loop.
1842 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1843 this, OSMemberFunctionCast(IOEventSource::Action, this,
1844 &IOPMrootDomain::dispatchPowerEvent));
1845 gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1846
1847 _aotTimerES = IOTimerEventSource::timerEventSource(this,
1848 OSMemberFunctionCast(IOTimerEventSource::Action,
1849 this, &IOPMrootDomain::aotEvaluate));
1850 gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1851
1852 // Avoid publishing service early so gIOPMWorkLoop is
1853 // guaranteed to be initialized by rootDomain.
1854 publishPMRootDomain();
1855
1856 // create our power parent
1857 gPatriarch = new IORootParent;
1858 gPatriarch->init();
1859 gPatriarch->attach(this);
1860 gPatriarch->start(this);
1861 gPatriarch->addPowerChild(this);
1862
1863 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1864 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1865
1866 // install power change handler
1867 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1868
1869 #if DISPLAY_WRANGLER_PRESENT
1870 wranglerIdleSettings = OSDictionary::withCapacity(1);
1871 OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1872
1873 if (wranglerIdleSettings && wranglerIdlePeriod) {
1874 wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1875 wranglerIdlePeriod.get());
1876 }
1877
1878 #endif /* DISPLAY_WRANGLER_PRESENT */
1879
1880 lowLatencyAudioNotifierDict = OSDictionary::withCapacity(2);
1881 lowLatencyAudioNotifyStateSym = OSSymbol::withCString("LowLatencyAudioNotifyState");
1882 lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1883 lowLatencyAudioNotifyStateVal = OSNumber::withNumber(0ull, 32);
1884 lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64);
1885
1886 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1887 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1888 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1889 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1890 }
1891
1892 OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1893 setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1894
1895 // IOBacklightDisplay can take a long time to load at boot, or it may
1896 // not load at all if you're booting with clamshell closed. We publish
1897 // 'DisplayDims' here redundantly to get it published early and at all.
1898 OSSharedPtr<OSDictionary> matching;
1899 matching = serviceMatching("IOPMPowerSource");
1900 psIterator = getMatchingServices(matching.get());
1901
1902 if (psIterator && psIterator->getNextObject()) {
1903 // There's at least one battery on the system, so we publish
1904 // 'DisplayDims' support for the LCD.
1905 publishFeature("DisplayDims");
1906 }
1907
1908 // read swd_panic boot-arg
1909 PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1910 gWillShutdownSysctlRegistered = true;
1911
1912 #if HIBERNATION
1913 IOHibernateSystemInit(this);
1914 #endif
1915
1916 registerService(); // let clients find us
1917
1918 return true;
1919 }
1920
1921 //******************************************************************************
1922 // setProperties
1923 //
1924 // Receive a setProperty call
1925 // The "System Boot" property means the system is completely booted.
1926 //******************************************************************************
1927
1928 IOReturn
setProperties(OSObject * props_obj)1929 IOPMrootDomain::setProperties( OSObject * props_obj )
1930 {
1931 IOReturn return_value = kIOReturnSuccess;
1932 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
1933 OSBoolean *b = NULL;
1934 OSNumber *n = NULL;
1935 const OSSymbol *key = NULL;
1936 OSObject *obj = NULL;
1937 OSSharedPtr<OSCollectionIterator> iter;
1938
1939 if (!dict) {
1940 return kIOReturnBadArgument;
1941 }
1942
1943 bool clientEntitled = false;
1944 {
1945 OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1946 clientEntitled = (obj == kOSBooleanTrue);
1947 }
1948
1949 if (!clientEntitled) {
1950 const char * errorSuffix = NULL;
1951
1952 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1953 // That API can set 6 possible keys that are checked below.
1954 if ((dict->getCount() == 1) &&
1955 (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) ||
1956 dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) ||
1957 dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) ||
1958 dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) ||
1959 dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) ||
1960 dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) {
1961 return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
1962 if (return_value != kIOReturnSuccess) {
1963 errorSuffix = "privileged";
1964 }
1965 } else {
1966 return_value = kIOReturnNotPermitted;
1967 errorSuffix = "entitled";
1968 }
1969
1970 if (return_value != kIOReturnSuccess) {
1971 OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain);
1972 DLOG("%s failed, process %s is not %s\n", __func__,
1973 procName ? procName->getCStringNoCopy() : "", errorSuffix);
1974 return return_value;
1975 }
1976 }
1977
1978 OSSharedPtr<const OSSymbol> publish_simulated_battery_string = OSSymbol::withCString("SoftwareSimulatedBatteries");
1979 OSSharedPtr<const OSSymbol> boot_complete_string = OSSymbol::withCString("System Boot Complete");
1980 OSSharedPtr<const OSSymbol> sys_shutdown_string = OSSymbol::withCString("System Shutdown");
1981 OSSharedPtr<const OSSymbol> stall_halt_string = OSSymbol::withCString("StallSystemAtHalt");
1982 OSSharedPtr<const OSSymbol> battery_warning_disabled_string = OSSymbol::withCString("BatteryWarningsDisabled");
1983 OSSharedPtr<const OSSymbol> idle_seconds_string = OSSymbol::withCString("System Idle Seconds");
1984 OSSharedPtr<const OSSymbol> idle_milliseconds_string = OSSymbol::withCString("System Idle Milliseconds");
1985 OSSharedPtr<const OSSymbol> sleepdisabled_string = OSSymbol::withCString("SleepDisabled");
1986 OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1987 OSSharedPtr<const OSSymbol> loginwindow_progress_string = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1988 OSSharedPtr<const OSSymbol> coredisplay_progress_string = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1989 OSSharedPtr<const OSSymbol> coregraphics_progress_string = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1990 #if DEBUG || DEVELOPMENT
1991 OSSharedPtr<const OSSymbol> clamshell_close_string = OSSymbol::withCString("IOPMTestClamshellClose");
1992 OSSharedPtr<const OSSymbol> clamshell_open_string = OSSymbol::withCString("IOPMTestClamshellOpen");
1993 OSSharedPtr<const OSSymbol> ac_detach_string = OSSymbol::withCString("IOPMTestACDetach");
1994 OSSharedPtr<const OSSymbol> ac_attach_string = OSSymbol::withCString("IOPMTestACAttach");
1995 OSSharedPtr<const OSSymbol> desktopmode_set_string = OSSymbol::withCString("IOPMTestDesktopModeSet");
1996 OSSharedPtr<const OSSymbol> desktopmode_remove_string = OSSymbol::withCString("IOPMTestDesktopModeRemove");
1997 #endif
1998
1999 #if HIBERNATION
2000 OSSharedPtr<const OSSymbol> hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey);
2001 OSSharedPtr<const OSSymbol> hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey);
2002 OSSharedPtr<const OSSymbol> hibernatefilemin_string = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
2003 OSSharedPtr<const OSSymbol> hibernatefilemax_string = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
2004 OSSharedPtr<const OSSymbol> hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey);
2005 OSSharedPtr<const OSSymbol> hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey);
2006 #endif
2007
2008 iter = OSCollectionIterator::withCollection(dict);
2009 if (!iter) {
2010 return_value = kIOReturnNoMemory;
2011 goto exit;
2012 }
2013
2014 while ((key = (const OSSymbol *) iter->getNextObject()) &&
2015 (obj = dict->getObject(key))) {
2016 if (key->isEqualTo(publish_simulated_battery_string.get())) {
2017 if (OSDynamicCast(OSBoolean, obj)) {
2018 publishResource(key, kOSBooleanTrue);
2019 }
2020 } else if (key->isEqualTo(idle_seconds_string.get())) {
2021 if ((n = OSDynamicCast(OSNumber, obj))) {
2022 setProperty(key, n);
2023 idleMilliSeconds = n->unsigned32BitValue() * 1000;
2024 }
2025 } else if (key->isEqualTo(idle_milliseconds_string.get())) {
2026 if ((n = OSDynamicCast(OSNumber, obj))) {
2027 setProperty(key, n);
2028 idleMilliSeconds = n->unsigned32BitValue();
2029 }
2030 } else if (key->isEqualTo(boot_complete_string.get())) {
2031 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
2032 } else if (key->isEqualTo(sys_shutdown_string.get())) {
2033 if ((b = OSDynamicCast(OSBoolean, obj))) {
2034 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
2035 }
2036 } else if (key->isEqualTo(battery_warning_disabled_string.get())) {
2037 setProperty(key, obj);
2038 }
2039 #if HIBERNATION
2040 else if (key->isEqualTo(hibernatemode_string.get()) ||
2041 key->isEqualTo(hibernatefilemin_string.get()) ||
2042 key->isEqualTo(hibernatefilemax_string.get()) ||
2043 key->isEqualTo(hibernatefreeratio_string.get()) ||
2044 key->isEqualTo(hibernatefreetime_string.get())) {
2045 if ((n = OSDynamicCast(OSNumber, obj))) {
2046 setProperty(key, n);
2047 }
2048 } else if (key->isEqualTo(hibernatefile_string.get())) {
2049 OSString * str = OSDynamicCast(OSString, obj);
2050 if (str) {
2051 setProperty(key, str);
2052 }
2053 }
2054 #endif
2055 else if (key->isEqualTo(sleepdisabled_string.get())) {
2056 if ((b = OSDynamicCast(OSBoolean, obj))) {
2057 setProperty(key, b);
2058 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
2059 }
2060 } else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
2061 obj->retain();
2062 pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
2063 } else if (key->isEqualTo(loginwindow_progress_string.get())) {
2064 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
2065 uint32_t data = n->unsigned32BitValue();
2066 pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
2067 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
2068 }
2069 } else if (key->isEqualTo(coredisplay_progress_string.get())) {
2070 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
2071 uint32_t data = n->unsigned32BitValue();
2072 pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
2073 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
2074 }
2075 } else if (key->isEqualTo(coregraphics_progress_string.get())) {
2076 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
2077 uint32_t data = n->unsigned32BitValue();
2078 pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
2079 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
2080 }
2081 } else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
2082 key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
2083 key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
2084 key->isEqualTo(stall_halt_string.get())) {
2085 if ((b = OSDynamicCast(OSBoolean, obj))) {
2086 setProperty(key, b);
2087 }
2088 } else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
2089 key->isEqualTo(kIOPMDeepSleepTimerKey) ||
2090 key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
2091 key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
2092 if ((n = OSDynamicCast(OSNumber, obj))) {
2093 setProperty(key, n);
2094 }
2095 } else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
2096 if (kOSBooleanTrue == obj) {
2097 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2098 } else {
2099 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2100 }
2101 DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
2102 }
2103 #if DEBUG || DEVELOPMENT
2104 else if (key->isEqualTo(clamshell_close_string.get())) {
2105 DLOG("SetProperties: setting clamshell close\n");
2106 UInt32 msg = kIOPMClamshellClosed;
2107 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2108 } else if (key->isEqualTo(clamshell_open_string.get())) {
2109 DLOG("SetProperties: setting clamshell open\n");
2110 UInt32 msg = kIOPMClamshellOpened;
2111 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2112 } else if (key->isEqualTo(ac_detach_string.get())) {
2113 DLOG("SetProperties: setting ac detach\n");
2114 UInt32 msg = kIOPMSetACAdaptorConnected;
2115 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2116 } else if (key->isEqualTo(ac_attach_string.get())) {
2117 DLOG("SetProperties: setting ac attach\n");
2118 UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue;
2119 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2120 } else if (key->isEqualTo(desktopmode_set_string.get())) {
2121 DLOG("SetProperties: setting desktopmode");
2122 UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue;
2123 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2124 } else if (key->isEqualTo(desktopmode_remove_string.get())) {
2125 DLOG("SetProperties: removing desktopmode\n");
2126 UInt32 msg = kIOPMSetDesktopMode;
2127 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2128 }
2129 #endif
2130 // Relay our allowed PM settings onto our registered PM clients
2131 else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
2132 return_value = setPMSetting(key, obj);
2133 if (kIOReturnSuccess != return_value) {
2134 break;
2135 }
2136 } else {
2137 DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
2138 }
2139 }
2140
2141 exit:
2142 return return_value;
2143 }
2144
2145 #if HIBERNATION
2146 // MARK: -
2147 // MARK: setLockdownModeHibernation
2148 // ***************************************************************************
2149 void
setLockdownModeHibernation(uint32_t status)2150 IOPMrootDomain::setLockdownModeHibernation(uint32_t status)
2151 {
2152 if (!gIOPMWorkLoop->inGate()) {
2153 gIOPMWorkLoop->runAction(
2154 OSMemberFunctionCast(IOWorkLoop::Action, this,
2155 &IOPMrootDomain::setLockdownModeHibernation),
2156 this, (void *)(uintptr_t) status);
2157 return;
2158 }
2159
2160 ldmHibernateDisable = status;
2161 DLOG("ldmHibernateDisable %d\n", status);
2162 setProperty("IOPMLDMHibernationDisable", status);
2163 }
2164 #endif
2165
2166 // MARK: -
2167 // MARK: Aggressiveness
2168
2169 //******************************************************************************
2170 // setAggressiveness
2171 //
2172 // Override IOService::setAggressiveness()
2173 //******************************************************************************
2174
2175 IOReturn
setAggressiveness(unsigned long type,unsigned long value)2176 IOPMrootDomain::setAggressiveness(
2177 unsigned long type,
2178 unsigned long value )
2179 {
2180 return setAggressiveness( type, value, 0 );
2181 }
2182
2183 /*
2184 * Private setAggressiveness() with an internal options argument.
2185 */
2186 IOReturn
setAggressiveness(unsigned long type,unsigned long value,IOOptionBits options)2187 IOPMrootDomain::setAggressiveness(
2188 unsigned long type,
2189 unsigned long value,
2190 IOOptionBits options )
2191 {
2192 AggressivesRequest * entry;
2193 AggressivesRequest * request;
2194 bool found = false;
2195
2196 if ((type > UINT_MAX) || (value > UINT_MAX)) {
2197 return kIOReturnBadArgument;
2198 }
2199
2200 if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2201 DLOG("setAggressiveness(%x) %s = %u\n",
2202 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2203 } else {
2204 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2205 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2206 }
2207
2208 request = IOMallocType(AggressivesRequest);
2209 request->options = options;
2210 request->dataType = kAggressivesRequestTypeRecord;
2211 request->data.record.type = (uint32_t) type;
2212 request->data.record.value = (uint32_t) value;
2213
2214 AGGRESSIVES_LOCK();
2215
2216 // Update disk quick spindown flag used by getAggressiveness().
2217 // Never merge requests with quick spindown flags set.
2218
2219 if (options & kAggressivesOptionQuickSpindownEnable) {
2220 gAggressivesState |= kAggressivesStateQuickSpindown;
2221 } else if (options & kAggressivesOptionQuickSpindownDisable) {
2222 gAggressivesState &= ~kAggressivesStateQuickSpindown;
2223 } else {
2224 // Coalesce requests with identical aggressives types.
2225 // Deal with callers that calls us too "aggressively".
2226
2227 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2228 {
2229 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2230 (entry->data.record.type == type) &&
2231 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2232 entry->data.record.value = (uint32_t) value;
2233 found = true;
2234 break;
2235 }
2236 }
2237 }
2238
2239 if (!found) {
2240 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2241 }
2242
2243 AGGRESSIVES_UNLOCK();
2244
2245 if (found) {
2246 IOFreeType(request, AggressivesRequest);
2247 }
2248
2249 if (options & kAggressivesOptionSynchronous) {
2250 handleAggressivesRequests(); // not truly synchronous
2251 } else {
2252 thread_call_enter(aggressivesThreadCall);
2253 }
2254
2255 return kIOReturnSuccess;
2256 }
2257
2258 //******************************************************************************
2259 // getAggressiveness
2260 //
2261 // Override IOService::setAggressiveness()
2262 // Fetch the aggressiveness factor with the given type.
2263 //******************************************************************************
2264
2265 IOReturn
getAggressiveness(unsigned long type,unsigned long * outLevel)2266 IOPMrootDomain::getAggressiveness(
2267 unsigned long type,
2268 unsigned long * outLevel )
2269 {
2270 uint32_t value = 0;
2271 int source = 0;
2272
2273 if (!outLevel || (type > UINT_MAX)) {
2274 return kIOReturnBadArgument;
2275 }
2276
2277 AGGRESSIVES_LOCK();
2278
2279 // Disk quick spindown in effect, report value = 1
2280
2281 if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2282 (type == kPMMinutesToSpinDown)) {
2283 value = kAggressivesMinValue;
2284 source = 1;
2285 }
2286
2287 // Consult the pending request queue.
2288
2289 if (!source) {
2290 AggressivesRequest * entry;
2291
2292 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2293 {
2294 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2295 (entry->data.record.type == type) &&
2296 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2297 value = entry->data.record.value;
2298 source = 2;
2299 break;
2300 }
2301 }
2302 }
2303
2304 // Consult the backend records.
2305
2306 if (!source && aggressivesData) {
2307 AggressivesRecord * record;
2308 int i, count;
2309
2310 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2311 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2312
2313 for (i = 0; i < count; i++, record++) {
2314 if (record->type == type) {
2315 value = record->value;
2316 source = 3;
2317 break;
2318 }
2319 }
2320 }
2321
2322 AGGRESSIVES_UNLOCK();
2323
2324 if (source) {
2325 *outLevel = (unsigned long) value;
2326 return kIOReturnSuccess;
2327 } else {
2328 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
2329 *outLevel = 0; // default return = 0, driver may not check for error
2330 return kIOReturnInvalid;
2331 }
2332 }
2333
2334 //******************************************************************************
2335 // joinAggressiveness
2336 //
2337 // Request from IOService to join future aggressiveness broadcasts.
2338 //******************************************************************************
2339
2340 IOReturn
joinAggressiveness(IOService * service)2341 IOPMrootDomain::joinAggressiveness(
2342 IOService * service )
2343 {
2344 AggressivesRequest * request;
2345
2346 if (!service || (service == this)) {
2347 return kIOReturnBadArgument;
2348 }
2349
2350 DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2351
2352 request = IOMallocType(AggressivesRequest);
2353 request->dataType = kAggressivesRequestTypeService;
2354 request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2355
2356 AGGRESSIVES_LOCK();
2357 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2358 AGGRESSIVES_UNLOCK();
2359
2360 thread_call_enter(aggressivesThreadCall);
2361
2362 return kIOReturnSuccess;
2363 }
2364
2365 //******************************************************************************
2366 // handleAggressivesRequests
2367 //
2368 // Backend thread processes all incoming aggressiveness requests in the queue.
2369 //******************************************************************************
2370
2371 static void
handleAggressivesFunction(thread_call_param_t param1,thread_call_param_t param2)2372 handleAggressivesFunction(
2373 thread_call_param_t param1,
2374 thread_call_param_t param2 )
2375 {
2376 if (param1) {
2377 ((IOPMrootDomain *) param1)->handleAggressivesRequests();
2378 }
2379 }
2380
2381 void
handleAggressivesRequests(void)2382 IOPMrootDomain::handleAggressivesRequests( void )
2383 {
2384 AggressivesRecord * start;
2385 AggressivesRecord * record;
2386 AggressivesRequest * request;
2387 queue_head_t joinedQueue;
2388 int i, count;
2389 bool broadcast;
2390 bool found;
2391 bool pingSelf = false;
2392
2393 AGGRESSIVES_LOCK();
2394
2395 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2396 queue_empty(&aggressivesQueue)) {
2397 goto unlock_done;
2398 }
2399
2400 gAggressivesState |= kAggressivesStateBusy;
2401 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2402 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2403
2404 do{
2405 broadcast = false;
2406 queue_init(&joinedQueue);
2407
2408 do{
2409 // Remove request from the incoming queue in FIFO order.
2410 queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
2411 switch (request->dataType) {
2412 case kAggressivesRequestTypeRecord:
2413 // Update existing record if found.
2414 found = false;
2415 for (i = 0, record = start; i < count; i++, record++) {
2416 if (record->type == request->data.record.type) {
2417 found = true;
2418
2419 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2420 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2421 broadcast = true;
2422 record->flags |= (kAggressivesRecordFlagMinValue |
2423 kAggressivesRecordFlagModified);
2424 DLOG("disk spindown accelerated, was %u min\n",
2425 record->value);
2426 }
2427 } else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2428 if (record->flags & kAggressivesRecordFlagMinValue) {
2429 broadcast = true;
2430 record->flags |= kAggressivesRecordFlagModified;
2431 record->flags &= ~kAggressivesRecordFlagMinValue;
2432 DLOG("disk spindown restored to %u min\n",
2433 record->value);
2434 }
2435 } else if (record->value != request->data.record.value) {
2436 record->value = request->data.record.value;
2437 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2438 broadcast = true;
2439 record->flags |= kAggressivesRecordFlagModified;
2440 }
2441 }
2442 break;
2443 }
2444 }
2445
2446 // No matching record, append a new record.
2447 if (!found &&
2448 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2449 AggressivesRecord newRecord;
2450
2451 newRecord.flags = kAggressivesRecordFlagModified;
2452 newRecord.type = request->data.record.type;
2453 newRecord.value = request->data.record.value;
2454 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2455 newRecord.flags |= kAggressivesRecordFlagMinValue;
2456 DLOG("disk spindown accelerated\n");
2457 }
2458
2459 aggressivesData->appendValue(newRecord);
2460
2461 // OSData may have switched to another (larger) buffer.
2462 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2463 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2464 broadcast = true;
2465 }
2466
2467 // Finished processing the request, release it.
2468 IOFreeType(request, AggressivesRequest);
2469 break;
2470
2471 case kAggressivesRequestTypeService:
2472 // synchronizeAggressives() will free request.
2473 queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2474 break;
2475
2476 default:
2477 panic("bad aggressives request type %x", request->dataType);
2478 break;
2479 }
2480 } while (!queue_empty(&aggressivesQueue));
2481
2482 // Release the lock to perform work, with busy flag set.
2483 if (!queue_empty(&joinedQueue) || broadcast) {
2484 AGGRESSIVES_UNLOCK();
2485 if (!queue_empty(&joinedQueue)) {
2486 synchronizeAggressives(&joinedQueue, start, count);
2487 }
2488 if (broadcast) {
2489 broadcastAggressives(start, count);
2490 }
2491 AGGRESSIVES_LOCK();
2492 }
2493
2494 // Remove the modified flag from all records.
2495 for (i = 0, record = start; i < count; i++, record++) {
2496 if ((record->flags & kAggressivesRecordFlagModified) &&
2497 ((record->type == kPMMinutesToDim) ||
2498 (record->type == kPMMinutesToSleep))) {
2499 pingSelf = true;
2500 }
2501
2502 record->flags &= ~kAggressivesRecordFlagModified;
2503 }
2504
2505 // Check the incoming queue again since new entries may have been
2506 // added while lock was released above.
2507 } while (!queue_empty(&aggressivesQueue));
2508
2509 gAggressivesState &= ~kAggressivesStateBusy;
2510
2511 unlock_done:
2512 AGGRESSIVES_UNLOCK();
2513
2514 // Root domain is interested in system and display sleep slider changes.
2515 // Submit a power event to handle those changes on the PM work loop.
2516
2517 if (pingSelf && pmPowerStateQueue) {
2518 pmPowerStateQueue->submitPowerEvent(
2519 kPowerEventPolicyStimulus,
2520 (void *) kStimulusAggressivenessChanged );
2521 }
2522 }
2523
2524 //******************************************************************************
2525 // synchronizeAggressives
2526 //
2527 // Push all known aggressiveness records to one or more IOService.
2528 //******************************************************************************
2529
2530 void
synchronizeAggressives(queue_head_t * joinedQueue,const AggressivesRecord * array,int count)2531 IOPMrootDomain::synchronizeAggressives(
2532 queue_head_t * joinedQueue,
2533 const AggressivesRecord * array,
2534 int count )
2535 {
2536 OSSharedPtr<IOService> service;
2537 AggressivesRequest * request;
2538 const AggressivesRecord * record;
2539 IOPMDriverCallEntry callEntry;
2540 uint32_t value;
2541 int i;
2542
2543 while (!queue_empty(joinedQueue)) {
2544 queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
2545 if (request->dataType == kAggressivesRequestTypeService) {
2546 // retained by joinAggressiveness(), so take ownership
2547 service = os::move(request->data.service);
2548 } else {
2549 service.reset();
2550 }
2551
2552 IOFreeType(request, AggressivesRequest);
2553 request = NULL;
2554
2555 if (service) {
2556 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2557 for (i = 0, record = array; i < count; i++, record++) {
2558 value = record->value;
2559 if (record->flags & kAggressivesRecordFlagMinValue) {
2560 value = kAggressivesMinValue;
2561 }
2562
2563 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2564 record->type, value, service->getName());
2565 service->setAggressiveness(record->type, value);
2566 }
2567 service->deassertPMDriverCall(&callEntry);
2568 }
2569 }
2570 }
2571 }
2572
2573 //******************************************************************************
2574 // broadcastAggressives
2575 //
2576 // Traverse PM tree and call setAggressiveness() for records that have changed.
2577 //******************************************************************************
2578
2579 void
broadcastAggressives(const AggressivesRecord * array,int count)2580 IOPMrootDomain::broadcastAggressives(
2581 const AggressivesRecord * array,
2582 int count )
2583 {
2584 OSSharedPtr<IORegistryIterator> iter;
2585 IORegistryEntry *entry;
2586 OSSharedPtr<IORegistryEntry> child;
2587 IOPowerConnection *connect;
2588 IOService *service;
2589 const AggressivesRecord *record;
2590 IOPMDriverCallEntry callEntry;
2591 uint32_t value;
2592 int i;
2593
2594 iter = IORegistryIterator::iterateOver(
2595 this, gIOPowerPlane, kIORegistryIterateRecursively);
2596 if (iter) {
2597 do{
2598 // !! reset the iterator
2599 iter->reset();
2600 while ((entry = iter->getNextObject())) {
2601 connect = OSDynamicCast(IOPowerConnection, entry);
2602 if (!connect || !connect->getReadyFlag()) {
2603 continue;
2604 }
2605
2606 child = connect->copyChildEntry(gIOPowerPlane);
2607 if (child) {
2608 if ((service = OSDynamicCast(IOService, child.get()))) {
2609 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2610 for (i = 0, record = array; i < count; i++, record++) {
2611 if (record->flags & kAggressivesRecordFlagModified) {
2612 value = record->value;
2613 if (record->flags & kAggressivesRecordFlagMinValue) {
2614 value = kAggressivesMinValue;
2615 }
2616 _LOG("broadcastAggressives %x = %u to %s\n",
2617 record->type, value, service->getName());
2618 service->setAggressiveness(record->type, value);
2619 }
2620 }
2621 service->deassertPMDriverCall(&callEntry);
2622 }
2623 }
2624 }
2625 }
2626 }while (!entry && !iter->isValid());
2627 }
2628 }
2629
2630 //*****************************************
2631 // stackshot on power button press
2632 // ***************************************
2633 static void
powerButtonDownCallout(thread_call_param_t us,thread_call_param_t)2634 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2635 {
2636 /* Power button pressed during wake
2637 * Take a stackshot
2638 */
2639 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2640 ((IOPMrootDomain *)us)->takeStackshot(false);
2641 }
2642
2643 static void
powerButtonUpCallout(thread_call_param_t us,thread_call_param_t)2644 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2645 {
2646 /* Power button released.
2647 * Delete any stackshot data
2648 */
2649 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2650 ((IOPMrootDomain *)us)->deleteStackshot();
2651 }
2652 //*************************************************************************
2653 //
2654
2655 // MARK: -
2656 // MARK: System Sleep
2657
2658 //******************************************************************************
2659 // startIdleSleepTimer
2660 //
2661 //******************************************************************************
2662
2663 void
startIdleSleepTimer(uint32_t inMilliSeconds)2664 IOPMrootDomain::startIdleSleepTimer( uint32_t inMilliSeconds )
2665 {
2666 AbsoluteTime deadline;
2667
2668 ASSERT_GATED();
2669 if (gNoIdleFlag) {
2670 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2671 return;
2672 }
2673 if (inMilliSeconds) {
2674 if (inMilliSeconds < kMinimumTimeBeforeIdleSleep) {
2675 AbsoluteTime now;
2676 uint64_t nsec_since_wake;
2677 uint64_t msec_since_wake;
2678
2679 // Adjust idle timer so it will not expire until atleast kMinimumTimeBeforeIdleSleep milliseconds
2680 // after the most recent AP wake.
2681 clock_get_uptime(&now);
2682 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2683 absolutetime_to_nanoseconds(now, &nsec_since_wake);
2684 msec_since_wake = nsec_since_wake / NSEC_PER_MSEC;
2685
2686 if (msec_since_wake < kMinimumTimeBeforeIdleSleep) {
2687 uint32_t newIdleTimer = kMinimumTimeBeforeIdleSleep - (uint32_t)msec_since_wake;
2688
2689 // Ensure that our new idle timer is not less than inMilliSeconds,
2690 // as we should only be increasing the timer duration, not decreasing it
2691 if (newIdleTimer > inMilliSeconds) {
2692 DLOG("startIdleSleepTimer increasing timeout from %u to %u\n", inMilliSeconds, newIdleTimer);
2693 inMilliSeconds = newIdleTimer;
2694 }
2695 }
2696 }
2697 clock_interval_to_deadline(inMilliSeconds, kMillisecondScale, &deadline);
2698 thread_call_enter_delayed(extraSleepTimer, deadline);
2699 idleSleepTimerPending = true;
2700 } else {
2701 thread_call_enter(extraSleepTimer);
2702 }
2703 DLOG("idle timer set for %u milliseconds\n", inMilliSeconds);
2704 }
2705
2706 //******************************************************************************
2707 // cancelIdleSleepTimer
2708 //
2709 //******************************************************************************
2710
2711 void
cancelIdleSleepTimer(void)2712 IOPMrootDomain::cancelIdleSleepTimer( void )
2713 {
2714 ASSERT_GATED();
2715 if (idleSleepTimerPending) {
2716 DLOG("idle timer cancelled\n");
2717 thread_call_cancel(extraSleepTimer);
2718 idleSleepTimerPending = false;
2719
2720 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2721 AbsoluteTime now;
2722 clock_usec_t microsecs;
2723 clock_get_uptime(&now);
2724 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2725 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
2726 if (assertOnWakeReport) {
2727 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2728 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2729 }
2730 }
2731 }
2732 }
2733
2734 //******************************************************************************
2735 // idleSleepTimerExpired
2736 //
2737 //******************************************************************************
2738
2739 static void
idleSleepTimerExpired(thread_call_param_t us,thread_call_param_t)2740 idleSleepTimerExpired(
2741 thread_call_param_t us, thread_call_param_t )
2742 {
2743 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2744 }
2745
2746 //******************************************************************************
2747 // handleSleepTimerExpiration
2748 //
2749 // The time between the sleep idle timeout and the next longest one has elapsed.
2750 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2751 //******************************************************************************
2752
2753 void
handleSleepTimerExpiration(void)2754 IOPMrootDomain::handleSleepTimerExpiration( void )
2755 {
2756 if (!gIOPMWorkLoop->inGate()) {
2757 gIOPMWorkLoop->runAction(
2758 OSMemberFunctionCast(IOWorkLoop::Action, this,
2759 &IOPMrootDomain::handleSleepTimerExpiration),
2760 this);
2761 return;
2762 }
2763
2764 DLOG("sleep timer expired\n");
2765 ASSERT_GATED();
2766
2767 idleSleepTimerPending = false;
2768 setQuickSpinDownTimeout();
2769 adjustPowerState(true);
2770 }
2771
2772 //******************************************************************************
2773 // getTimeToIdleSleep
2774 //
2775 // Returns number of milliseconds left before going into idle sleep.
2776 // Caller has to make sure that idle sleep is allowed at the time of calling
2777 // this function
2778 //******************************************************************************
2779
2780 uint32_t
getTimeToIdleSleep(void)2781 IOPMrootDomain::getTimeToIdleSleep( void )
2782 {
2783 AbsoluteTime now, lastActivityTime;
2784 uint64_t nanos;
2785 uint32_t minutesSinceUserInactive = 0;
2786 uint32_t sleepDelay = 0;
2787
2788 if (!idleSleepEnabled) {
2789 return 0xffffffff;
2790 }
2791
2792 if (userActivityTime) {
2793 lastActivityTime = userActivityTime;
2794 } else {
2795 lastActivityTime = userBecameInactiveTime;
2796 }
2797
2798 // Ignore any lastActivityTime that predates the last system wake.
2799 // The goal is to avoid a sudden idle sleep right after a dark wake
2800 // due to sleepDelay=0 computed below. The alternative 60s minimum
2801 // timeout should be large enough to allow dark wake to complete,
2802 // at which point the idle timer will be promptly cancelled.
2803 clock_get_uptime(&now);
2804 if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) &&
2805 (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) {
2806 SUB_ABSOLUTETIME(&now, &lastActivityTime);
2807 absolutetime_to_nanoseconds(now, &nanos);
2808 minutesSinceUserInactive = nanos / (60000000000ULL);
2809
2810 if (minutesSinceUserInactive >= sleepSlider) {
2811 sleepDelay = 0;
2812 } else {
2813 sleepDelay = sleepSlider - minutesSinceUserInactive;
2814 }
2815 } else {
2816 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2817 lastActivityTime, now, gIOLastWakeAbsTime);
2818 sleepDelay = sleepSlider;
2819 }
2820
2821 DLOG("user inactive %u min, time to idle sleep %u min\n",
2822 minutesSinceUserInactive, sleepDelay);
2823
2824 return sleepDelay * 60 * 1000;
2825 }
2826
2827 //******************************************************************************
2828 // setQuickSpinDownTimeout
2829 //
2830 //******************************************************************************
2831
2832 void
setQuickSpinDownTimeout(void)2833 IOPMrootDomain::setQuickSpinDownTimeout( void )
2834 {
2835 ASSERT_GATED();
2836 setAggressiveness(
2837 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2838 }
2839
2840 //******************************************************************************
2841 // restoreUserSpinDownTimeout
2842 //
2843 //******************************************************************************
2844
2845 void
restoreUserSpinDownTimeout(void)2846 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2847 {
2848 ASSERT_GATED();
2849 setAggressiveness(
2850 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2851 }
2852
2853 //******************************************************************************
2854 // sleepSystem
2855 //
2856 //******************************************************************************
2857
2858 /* public */
2859 IOReturn
sleepSystem(void)2860 IOPMrootDomain::sleepSystem( void )
2861 {
2862 return sleepSystemOptions(NULL);
2863 }
2864
2865 /* private */
2866 IOReturn
sleepSystemOptions(OSDictionary * options)2867 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2868 {
2869 OSObject *obj = NULL;
2870 OSString *reason = NULL;
2871 /* sleepSystem is a public function, and may be called by any kernel driver.
2872 * And that's bad - drivers should sleep the system by calling
2873 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2874 *
2875 * Note that user space app calls to IOPMSleepSystem() will also travel
2876 * this code path and thus be correctly identified as software sleeps.
2877 */
2878
2879 if (options && options->getObject("OSSwitch")) {
2880 // Log specific sleep cause for OS Switch hibernation
2881 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2882 }
2883
2884 if (options && (obj = options->getObject("Sleep Reason"))) {
2885 reason = OSDynamicCast(OSString, obj);
2886 if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2887 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2888 }
2889 if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2890 return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2891 }
2892 }
2893
2894 return privateSleepSystem( kIOPMSleepReasonSoftware);
2895 }
2896
2897 /* private */
2898 IOReturn
privateSleepSystem(uint32_t sleepReason)2899 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2900 {
2901 /* Called from both gated and non-gated context */
2902
2903 if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2904 return kIOReturnNotPermitted;
2905 }
2906
2907 pmPowerStateQueue->submitPowerEvent(
2908 kPowerEventPolicyStimulus,
2909 (void *) kStimulusDemandSystemSleep,
2910 sleepReason);
2911
2912 return kIOReturnSuccess;
2913 }
2914
2915 //******************************************************************************
2916 // powerChangeDone
2917 //
2918 // This overrides powerChangeDone in IOService.
2919 //******************************************************************************
2920 void
powerChangeDone(unsigned long previousPowerState)2921 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2922 {
2923 #if !__i386__ && !__x86_64__
2924 uint64_t timeSinceReset = 0;
2925 #endif
2926 uint64_t now;
2927 unsigned long newState;
2928 clock_sec_t secs;
2929 clock_usec_t microsecs;
2930 uint32_t lastDebugWakeSeconds;
2931 clock_sec_t adjWakeTime;
2932 IOPMCalendarStruct nowCalendar;
2933
2934 ASSERT_GATED();
2935 newState = getPowerState();
2936 DLOG("PowerChangeDone: %s->%s\n",
2937 getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2938
2939 if (previousPowerState == newState) {
2940 return;
2941 }
2942
2943 notifierThread = current_thread();
2944 switch (getPowerState()) {
2945 case SLEEP_STATE: {
2946 if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionForceWakeupBit)) {
2947 IOLog("accelerate wake for assertion\n");
2948 setWakeTime(mach_continuous_time());
2949 }
2950 if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionForceFullWakeupBit)) {
2951 // Note: The scheduled RTC wakeup will trigger a full wake.
2952 scheduleImmediateDebugWake();
2953 }
2954
2955 if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2956 secs = 0;
2957 microsecs = 0;
2958 PEGetUTCTimeOfDay(&secs, µsecs);
2959
2960 adjWakeTime = 0;
2961 if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) {
2962 IOLog("use _calendarWakeAlarmUTC\n");
2963 adjWakeTime = _calendarWakeAlarmUTC;
2964 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
2965 IOLog("accelerate _aotWakeTime for exit\n");
2966 adjWakeTime = secs;
2967 } else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2968 IOLog("accelerate _aotWakeTime for assertion\n");
2969 adjWakeTime = secs;
2970 }
2971 if (adjWakeTime) {
2972 IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2973 }
2974
2975 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2976 IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2977
2978 IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2979 assert(kIOReturnSuccess == ret);
2980 }
2981 if (_aotLastWakeTime) {
2982 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
2983 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
2984 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
2985 gWakeReasonString,
2986 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2987 }
2988 }
2989 _aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2990 if (_aotTimerScheduled) {
2991 _aotTimerES->cancelTimeout();
2992 _aotTimerScheduled = false;
2993 }
2994 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2995
2996 // re-enable this timer for next sleep
2997 cancelIdleSleepTimer();
2998
2999 if (clamshellExists) {
3000 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
3001 if (gClamshellFlags & kClamshell_WAR_58009435) {
3002 // Disable clamshell sleep until system has completed full wake.
3003 // This prevents a system sleep request (due to a clamshell close)
3004 // from being queued until the end of system full wake - even if
3005 // other clamshell disable bits outside of our control is wrong.
3006 setClamShellSleepDisable(true, kClamshellSleepDisableInternal);
3007 }
3008 #endif
3009
3010 // Log the last known clamshell state before system sleep
3011 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
3012 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask,
3013 desktopMode, acAdaptorConnected);
3014 }
3015
3016 clock_get_calendar_absolute_and_microtime(&secs, µsecs, &now);
3017 logtime(secs);
3018 gIOLastSleepTime.tv_sec = secs;
3019 gIOLastSleepTime.tv_usec = microsecs;
3020 if (!_aotLastWakeTime) {
3021 gIOLastUserSleepTime = gIOLastSleepTime;
3022 }
3023 gIOLastWakeTime.tv_sec = 0;
3024 gIOLastWakeTime.tv_usec = 0;
3025 gIOLastSleepAbsTime = now;
3026
3027 if (wake2DarkwakeDelay && sleepDelaysReport) {
3028 clock_sec_t wake2DarkwakeSecs, darkwake2SleepSecs;
3029 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
3030
3031 SUB_ABSOLUTETIME(&now, &ts_sleepStart);
3032 absolutetime_to_microtime(now, &darkwake2SleepSecs, µsecs);
3033 absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, µsecs);
3034 HISTREPORT_TALLYVALUE(sleepDelaysReport,
3035 (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
3036
3037 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
3038 wake2DarkwakeDelay = 0;
3039 }
3040 #if HIBERNATION
3041 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
3042 #if (DEVELOPMENT || DEBUG)
3043 record_system_event(SYSTEM_EVENT_TYPE_INFO,
3044 SYSTEM_EVENT_SUBSYSTEM_PMRD,
3045 "System State",
3046 gIOHibernateState ? "Enter Hibernate" : "Enter Sleep"
3047 );
3048 #endif /* DEVELOPMENT || DEBUG */
3049 IOHibernateSystemHasSlept();
3050
3051 evaluateSystemSleepPolicyFinal();
3052 #else
3053 LOG("System Sleep\n");
3054 #if (DEVELOPMENT || DEBUG)
3055 record_system_event(SYSTEM_EVENT_TYPE_INFO,
3056 SYSTEM_EVENT_SUBSYSTEM_PMRD,
3057 "System State", "Enter Sleep");
3058 #endif /* DEVELOPMENT || DEBUG */
3059 #endif
3060 if (thermalWarningState) {
3061 OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
3062 if (event) {
3063 systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
3064 }
3065 }
3066 assertOnWakeSecs = 0;
3067 lowBatteryCondition = false;
3068 thermalEmergencyState = false;
3069
3070 #if DEVELOPMENT || DEBUG
3071 extern int g_should_log_clock_adjustments;
3072 if (g_should_log_clock_adjustments) {
3073 clock_sec_t secs = 0;
3074 clock_usec_t microsecs = 0;
3075 uint64_t now_b = mach_absolute_time();
3076
3077 secs = 0;
3078 microsecs = 0;
3079 PEGetUTCTimeOfDay(&secs, µsecs);
3080
3081 uint64_t now_a = mach_absolute_time();
3082 os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
3083 __func__, (unsigned long)secs, microsecs, now_b, now_a);
3084 }
3085 #endif
3086
3087 getPlatform()->sleepKernel();
3088
3089 // The CPU(s) are off at this point,
3090 // Code will resume execution here upon wake.
3091
3092 clock_get_uptime(&gIOLastWakeAbsTime);
3093 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
3094 #if DEVELOPMENT || DEBUG
3095 record_system_event(SYSTEM_EVENT_TYPE_INFO,
3096 SYSTEM_EVENT_SUBSYSTEM_PMRD,
3097 "System State", "Waking Up"
3098 );
3099 #endif /* DEVELOPMENT || DEBUG */
3100 _highestCapability = 0;
3101
3102 #if HIBERNATION
3103 IOHibernateSystemWake();
3104 #endif
3105
3106 // sleep transition complete
3107 gSleepOrShutdownPending = 0;
3108
3109 // trip the reset of the calendar clock
3110 clock_wakeup_calendar();
3111 clock_get_calendar_microtime(&secs, µsecs);
3112 gIOLastWakeTime.tv_sec = secs;
3113 gIOLastWakeTime.tv_usec = microsecs;
3114
3115 // aot
3116 if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
3117 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
3118 secs = 0;
3119 microsecs = 0;
3120 PEGetUTCTimeOfDay(&secs, µsecs);
3121 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
3122 IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
3123 _aotMetrics->sleepCount++;
3124 _aotLastWakeTime = gIOLastWakeAbsTime;
3125 if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
3126 _aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
3127 = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
3128 _aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
3129 = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
3130 }
3131
3132 if (_aotTestTime) {
3133 if (_aotWakeTimeUTC <= secs) {
3134 _aotTestTime = mach_continuous_time() + _aotTestInterval;
3135 }
3136 if (_aotTestTime < _aotEndTime) {
3137 _setWakeTime(_aotTestTime);
3138 }
3139 }
3140 }
3141
3142 #if HIBERNATION
3143 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
3144 #endif
3145
3146 lastSleepReason = 0;
3147
3148 lastDebugWakeSeconds = _debugWakeSeconds;
3149 _debugWakeSeconds = 0;
3150 _scheduledAlarmMask = 0;
3151 _nextScheduledAlarmType = NULL;
3152
3153 darkWakeExit = false;
3154 darkWakePowerClamped = false;
3155 darkWakePostTickle = false;
3156 darkWakeHibernateError = false;
3157 darkWakeToSleepASAP = true;
3158 darkWakeLogClamp = true;
3159 sleepTimerMaintenance = false;
3160 sleepToStandby = false;
3161 wranglerTickled = false;
3162 userWasActive = false;
3163 isRTCAlarmWake = false;
3164 clamshellIgnoreClose = false;
3165 fullWakeReason = kFullWakeReasonNone;
3166 idleSleepRevertible = true;
3167
3168 #if defined(__i386__) || defined(__x86_64__)
3169 kdebugTrace(kPMLogSystemWake, 0, 0, 0);
3170
3171 OSSharedPtr<OSObject> wakeTypeProp = copyProperty(kIOPMRootDomainWakeTypeKey);
3172 OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey);
3173 OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get());
3174 OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get());
3175
3176 if (wakeReason && (wakeReason->getLength() >= 2) &&
3177 gWakeReasonString[0] == '\0') {
3178 WAKEEVENT_LOCK();
3179 // Until the platform driver can claim its wake reasons
3180 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
3181 sizeof(gWakeReasonString));
3182 if (!gWakeReasonSysctlRegistered) {
3183 gWakeReasonSysctlRegistered = true;
3184 }
3185 WAKEEVENT_UNLOCK();
3186 }
3187
3188 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
3189 lowBatteryCondition = true;
3190 darkWakeMaintenance = true;
3191 } else {
3192 #if HIBERNATION
3193 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3194 OSNumber * hibOptions = OSDynamicCast( OSNumber, hibOptionsProp.get());
3195 if (hibernateAborted || ((hibOptions &&
3196 !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
3197 // Hibernate aborted, or EFI brought up graphics
3198 darkWakeExit = true;
3199 if (hibernateAborted) {
3200 DLOG("Hibernation aborted\n");
3201 } else {
3202 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
3203 }
3204 } else
3205 #endif
3206 if (wakeType && (
3207 wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
3208 wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
3209 // User wake or RTC alarm
3210 darkWakeExit = true;
3211 if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
3212 isRTCAlarmWake = true;
3213 }
3214 } else if (wakeType &&
3215 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
3216 // SMC standby timer trumps SleepX
3217 darkWakeMaintenance = true;
3218 sleepTimerMaintenance = true;
3219 } else if ((lastDebugWakeSeconds != 0) &&
3220 ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
3221 // SleepX before maintenance
3222 darkWakeExit = true;
3223 } else if (wakeType &&
3224 wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
3225 darkWakeMaintenance = true;
3226 } else if (wakeType &&
3227 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
3228 darkWakeMaintenance = true;
3229 darkWakeSleepService = true;
3230 #if HIBERNATION
3231 if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3232 sleepToStandby = true;
3233 }
3234 #endif
3235 } else if (wakeType &&
3236 wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3237 darkWakeMaintenance = true;
3238 darkWakeHibernateError = true;
3239 } else {
3240 // Unidentified wake source, resume to full wake if debug
3241 // alarm is pending.
3242
3243 if (lastDebugWakeSeconds &&
3244 (!wakeReason || wakeReason->isEqualTo(""))) {
3245 darkWakeExit = true;
3246 }
3247 }
3248 }
3249
3250 if (darkWakeExit) {
3251 darkWakeToSleepASAP = false;
3252 fullWakeReason = kFullWakeReasonLocalUser;
3253 reportUserInput();
3254 } else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
3255 handleSetDisplayPowerOn(true);
3256 } else if (!darkWakeMaintenance) {
3257 // Early/late tickle for non-maintenance wake.
3258 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) {
3259 darkWakePostTickle = true;
3260 }
3261 }
3262 #else /* !__i386__ && !__x86_64__ */
3263 timeSinceReset = ml_get_time_since_reset();
3264 kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3265
3266 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) {
3267 wranglerTickled = true;
3268 fullWakeReason = kFullWakeReasonLocalUser;
3269 requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3270 } else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
3271 isRTCAlarmWake = true;
3272 fullWakeReason = kFullWakeReasonLocalUser;
3273 requestUserActive(this, "RTC debug alarm");
3274 } else {
3275 #if HIBERNATION
3276 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3277 OSNumber * hibOptions = OSDynamicCast(OSNumber, hibOptionsProp.get());
3278 if (hibOptions && !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)) {
3279 fullWakeReason = kFullWakeReasonLocalUser;
3280 requestUserActive(this, "hibernate user wake");
3281 }
3282 #endif
3283 }
3284
3285 // stay awake for at least 30 seconds
3286 startIdleSleepTimer(30 * 1000);
3287 #endif
3288 sleepCnt++;
3289
3290 thread_call_enter(updateConsoleUsersEntry);
3291
3292 // Skip AOT_STATE if we are waking up from an RTC timer.
3293 // This check needs to be done after the epoch change is processed
3294 // and before the changePowerStateWithTagToPriv() call below.
3295 WAKEEVENT_LOCK();
3296 aotShouldExit(false);
3297 unsigned long newState = getRUN_STATE();
3298 if (AOT_STATE == newState) {
3299 _aotRunMode = gLPWFlags;
3300 }
3301 WAKEEVENT_UNLOCK();
3302
3303 changePowerStateWithTagToPriv(newState, kCPSReasonWake);
3304 break;
3305 }
3306 #if !__i386__ && !__x86_64__
3307 case ON_STATE:
3308 case AOT_STATE:
3309 {
3310 DLOG("Force re-evaluating aggressiveness\n");
3311 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3312 pmPowerStateQueue->submitPowerEvent(
3313 kPowerEventPolicyStimulus,
3314 (void *) kStimulusNoIdleSleepPreventers );
3315
3316 // After changing to ON_STATE, invalidate any previously queued
3317 // request to change to a state less than ON_STATE. This isn't
3318 // necessary for AOT_STATE or if the device has only one running
3319 // state since the changePowerStateToPriv() issued at the tail
3320 // end of SLEEP_STATE case should take care of that.
3321 if (getPowerState() == ON_STATE) {
3322 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake);
3323 }
3324 break;
3325 }
3326 #endif /* !__i386__ && !__x86_64__ */
3327 }
3328 notifierThread = NULL;
3329 }
3330
3331 //******************************************************************************
3332 // requestPowerDomainState
3333 //
3334 // Extend implementation in IOService. Running on PM work loop thread.
3335 //******************************************************************************
3336
3337 IOReturn
requestPowerDomainState(IOPMPowerFlags childDesire,IOPowerConnection * childConnection,unsigned long specification)3338 IOPMrootDomain::requestPowerDomainState(
3339 IOPMPowerFlags childDesire,
3340 IOPowerConnection * childConnection,
3341 unsigned long specification )
3342 {
3343 // Idle and system sleep prevention flags affects driver desire.
3344 // Children desire are irrelevant so they are cleared.
3345
3346 return super::requestPowerDomainState(0, childConnection, specification);
3347 }
3348
3349
3350 static void
makeSleepPreventersListLog(const OSSharedPtr<OSSet> & preventers,char * buf,size_t buf_size)3351 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3352 {
3353 if (!preventers->getCount()) {
3354 return;
3355 }
3356
3357 char *buf_iter = buf + strlen(buf);
3358 char *buf_end = buf + buf_size;
3359
3360 OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3361 OSObject *obj = NULL;
3362
3363 while ((obj = iterator->getNextObject())) {
3364 IOService *srv = OSDynamicCast(IOService, obj);
3365 if (buf_iter < buf_end) {
3366 buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName());
3367 } else {
3368 DLOG("Print buffer exhausted for sleep preventers list\n");
3369 break;
3370 }
3371 }
3372 }
3373
3374 //******************************************************************************
3375 // updatePreventIdleSleepList
3376 //
3377 // Called by IOService on PM work loop.
3378 // Returns true if PM policy recognized the driver's desire to prevent idle
3379 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3380 //******************************************************************************
3381
3382 bool
updatePreventIdleSleepList(IOService * service,bool addNotRemove)3383 IOPMrootDomain::updatePreventIdleSleepList(
3384 IOService * service, bool addNotRemove)
3385 {
3386 unsigned int oldCount;
3387
3388 oldCount = idleSleepPreventersCount();
3389 return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3390 }
3391
3392 bool
updatePreventIdleSleepListInternal(IOService * service,bool addNotRemove,unsigned int oldCount)3393 IOPMrootDomain::updatePreventIdleSleepListInternal(
3394 IOService * service, bool addNotRemove, unsigned int oldCount)
3395 {
3396 unsigned int newCount;
3397
3398 ASSERT_GATED();
3399
3400 #if defined(XNU_TARGET_OS_OSX)
3401 // Only the display wrangler and no-idle-sleep kernel assertions
3402 // can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3403 // reported by drivers in their power state table is ignored.
3404 if (service && (service != wrangler) && (service != this)) {
3405 return false;
3406 }
3407 #endif
3408
3409 if (service) {
3410 if (addNotRemove) {
3411 preventIdleSleepList->setObject(service);
3412 DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3413 service->getName(), preventIdleSleepList->getCount());
3414 } else if (preventIdleSleepList->member(service)) {
3415 preventIdleSleepList->removeObject(service);
3416 DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3417 service->getName(), preventIdleSleepList->getCount());
3418 }
3419
3420 if (preventIdleSleepList->getCount()) {
3421 char buf[256] = "Idle Sleep Preventers:";
3422 makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3423 DLOG("%s\n", buf);
3424 }
3425 }
3426
3427 newCount = idleSleepPreventersCount();
3428
3429 if ((oldCount == 0) && (newCount != 0)) {
3430 // Driver added to empty prevent list.
3431 // Update the driver desire to prevent idle sleep.
3432 // Driver desire does not prevent demand sleep.
3433
3434 changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent);
3435 } else if ((oldCount != 0) && (newCount == 0)) {
3436 // Last driver removed from prevent list.
3437 // Drop the driver clamp to allow idle sleep.
3438
3439 changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3440 evaluatePolicy( kStimulusNoIdleSleepPreventers );
3441 }
3442 messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3443 &newCount, sizeof(newCount));
3444
3445 #if defined(XNU_TARGET_OS_OSX)
3446 if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
3447 DLOG("Cannot cancel idle sleep\n");
3448 return false; // do not idle-cancel
3449 }
3450 #endif
3451
3452 return true;
3453 }
3454
3455 //******************************************************************************
3456 // startSpinDump
3457 //******************************************************************************
3458
3459 void
startSpinDump(uint32_t spindumpKind)3460 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3461 {
3462 messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3463 }
3464
3465 //******************************************************************************
3466 // preventSystemSleepListUpdate
3467 //
3468 // Called by IOService on PM work loop.
3469 //******************************************************************************
3470
3471 void
updatePreventSystemSleepList(IOService * service,bool addNotRemove)3472 IOPMrootDomain::updatePreventSystemSleepList(
3473 IOService * service, bool addNotRemove )
3474 {
3475 unsigned int oldCount, newCount;
3476
3477 ASSERT_GATED();
3478 if (this == service) {
3479 return;
3480 }
3481
3482 oldCount = preventSystemSleepList->getCount();
3483 if (addNotRemove) {
3484 preventSystemSleepList->setObject(service);
3485 DLOG("Added %s to system sleep preventers list (Total %u)\n",
3486 service->getName(), preventSystemSleepList->getCount());
3487 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
3488 AbsoluteTime now;
3489 clock_usec_t microsecs;
3490 clock_get_uptime(&now);
3491 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3492 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
3493 if (assertOnWakeReport) {
3494 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3495 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3496 }
3497 }
3498 } else if (preventSystemSleepList->member(service)) {
3499 preventSystemSleepList->removeObject(service);
3500 DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3501 service->getName(), preventSystemSleepList->getCount());
3502
3503 if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
3504 // Lost all system sleep preventers.
3505 // Send stimulus if system sleep was blocked, and is in dark wake.
3506 evaluatePolicy( kStimulusDarkWakeEvaluate );
3507 }
3508 }
3509
3510 newCount = preventSystemSleepList->getCount();
3511 if (newCount) {
3512 char buf[256] = "System Sleep Preventers:";
3513 makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3514 DLOG("%s\n", buf);
3515 }
3516
3517 messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3518 &newCount, sizeof(newCount));
3519 }
3520
3521 void
copySleepPreventersList(OSArray ** idleSleepList,OSArray ** systemSleepList)3522 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3523 {
3524 OSSharedPtr<OSCollectionIterator> iterator;
3525 OSObject *object = NULL;
3526 OSSharedPtr<OSArray> array;
3527
3528 if (!gIOPMWorkLoop->inGate()) {
3529 gIOPMWorkLoop->runAction(
3530 OSMemberFunctionCast(IOWorkLoop::Action, this,
3531 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3532 this, (void *)idleSleepList, (void *)systemSleepList);
3533 return;
3534 }
3535
3536 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3537 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3538 array = OSArray::withCapacity(5);
3539
3540 if (iterator && array) {
3541 while ((object = iterator->getNextObject())) {
3542 IOService *service = OSDynamicCast(IOService, object);
3543 if (service) {
3544 OSSharedPtr<const OSSymbol> name = service->copyName();
3545 if (name) {
3546 array->setObject(name.get());
3547 }
3548 }
3549 }
3550 }
3551 *idleSleepList = array.detach();
3552 }
3553
3554 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3555 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3556 array = OSArray::withCapacity(5);
3557
3558 if (iterator && array) {
3559 while ((object = iterator->getNextObject())) {
3560 IOService *service = OSDynamicCast(IOService, object);
3561 if (service) {
3562 OSSharedPtr<const OSSymbol> name = service->copyName();
3563 if (name) {
3564 array->setObject(name.get());
3565 }
3566 }
3567 }
3568 }
3569 *systemSleepList = array.detach();
3570 }
3571 }
3572
3573 void
copySleepPreventersListWithID(OSArray ** idleSleepList,OSArray ** systemSleepList)3574 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3575 {
3576 OSSharedPtr<OSCollectionIterator> iterator;
3577 OSObject *object = NULL;
3578 OSSharedPtr<OSArray> array;
3579
3580 if (!gIOPMWorkLoop->inGate()) {
3581 gIOPMWorkLoop->runAction(
3582 OSMemberFunctionCast(IOWorkLoop::Action, this,
3583 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3584 this, (void *)idleSleepList, (void *)systemSleepList);
3585 return;
3586 }
3587
3588 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3589 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3590 array = OSArray::withCapacity(5);
3591
3592 if (iterator && array) {
3593 while ((object = iterator->getNextObject())) {
3594 IOService *service = OSDynamicCast(IOService, object);
3595 if (service) {
3596 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3597 OSSharedPtr<const OSSymbol> name = service->copyName();
3598 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3599 if (dict && name && id) {
3600 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3601 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3602 array->setObject(dict.get());
3603 }
3604 }
3605 }
3606 }
3607 *idleSleepList = array.detach();
3608 }
3609
3610 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3611 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3612 array = OSArray::withCapacity(5);
3613
3614 if (iterator && array) {
3615 while ((object = iterator->getNextObject())) {
3616 IOService *service = OSDynamicCast(IOService, object);
3617 if (service) {
3618 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3619 OSSharedPtr<const OSSymbol> name = service->copyName();
3620 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3621 if (dict && name && id) {
3622 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3623 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3624 array->setObject(dict.get());
3625 }
3626 }
3627 }
3628 }
3629 *systemSleepList = array.detach();
3630 }
3631 }
3632
3633 //******************************************************************************
3634 // tellChangeDown
3635 //
3636 // Override the superclass implementation to send a different message type.
3637 //******************************************************************************
3638
3639 bool
tellChangeDown(unsigned long stateNum)3640 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3641 {
3642 DLOG("tellChangeDown %s->%s\n",
3643 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3644
3645 if (SLEEP_STATE == stateNum) {
3646 // Legacy apps were already told in the full->dark transition
3647 if (!ignoreTellChangeDown) {
3648 tracePoint( kIOPMTracePointSleepApplications );
3649 } else {
3650 tracePoint( kIOPMTracePointSleepPriorityClients );
3651 }
3652 }
3653
3654 if (!ignoreTellChangeDown) {
3655 userActivityAtSleep = userActivityCount;
3656 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3657
3658 if (SLEEP_STATE == stateNum) {
3659 hibernateAborted = false;
3660
3661 // Direct callout into OSKext so it can disable kext unloads
3662 // during sleep/wake to prevent deadlocks.
3663 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3664
3665 IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3666
3667 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3668 // But tellClientsWithResponse() must be called for both.
3669 ignoreTellChangeDown = true;
3670 }
3671 }
3672
3673 return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3674 }
3675
3676 //******************************************************************************
3677 // askChangeDown
3678 //
3679 // Override the superclass implementation to send a different message type.
3680 // This must be idle sleep since we don't ask during any other power change.
3681 //******************************************************************************
3682
3683 bool
askChangeDown(unsigned long stateNum)3684 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3685 {
3686 DLOG("askChangeDown %s->%s\n",
3687 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3688
3689 // Don't log for dark wake entry
3690 if (kSystemTransitionSleep == _systemTransitionType) {
3691 tracePoint( kIOPMTracePointSleepApplications );
3692 }
3693
3694 return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3695 }
3696
3697 //******************************************************************************
3698 // askChangeDownDone
3699 //
3700 // An opportunity for root domain to cancel the power transition,
3701 // possibily due to an assertion created by powerd in response to
3702 // kIOMessageCanSystemSleep.
3703 //
3704 // Idle sleep:
3705 // full -> dark wake transition
3706 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3707 // 2. askChangeDownDone()
3708 // dark -> sleep transition
3709 // 1. Notify powerd with kIOMessageCanSystemSleep
3710 // 2. askChangeDownDone()
3711 //
3712 // Demand sleep:
3713 // full -> dark wake transition
3714 // 1. Notify powerd with kIOMessageCanSystemSleep
3715 // 2. askChangeDownDone()
3716 // dark -> sleep transition
3717 // 1. Notify powerd with kIOMessageCanSystemSleep
3718 // 2. askChangeDownDone()
3719 //******************************************************************************
3720
3721 void
askChangeDownDone(IOPMPowerChangeFlags * inOutChangeFlags,bool * cancel)3722 IOPMrootDomain::askChangeDownDone(
3723 IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3724 {
3725 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3726 *inOutChangeFlags, *cancel,
3727 _systemTransitionType,
3728 _currentCapability, _pendingCapability);
3729
3730 if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
3731 // Dark->Sleep transition.
3732 // Check if there are any deny sleep assertions.
3733 // lastSleepReason already set by handleOurPowerChangeStart()
3734
3735 if (!checkSystemCanSleep(lastSleepReason)) {
3736 // Cancel dark wake to sleep transition.
3737 // Must re-scan assertions upon entering dark wake.
3738
3739 *cancel = true;
3740 DLOG("cancel dark->sleep\n");
3741 }
3742 if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3743 uint64_t now = mach_continuous_time();
3744 if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3745 && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3746 *cancel = true;
3747 IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3748 }
3749 }
3750 }
3751 }
3752
3753 //******************************************************************************
3754 // systemDidNotSleep
3755 //
3756 // Work common to both canceled or aborted sleep.
3757 //******************************************************************************
3758
3759 void
systemDidNotSleep(void)3760 IOPMrootDomain::systemDidNotSleep( void )
3761 {
3762 // reset console lock state
3763 thread_call_enter(updateConsoleUsersEntry);
3764
3765 if (idleSleepEnabled) {
3766 if (!wrangler) {
3767 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3768 startIdleSleepTimer(kIdleSleepRetryInterval);
3769 #else
3770 startIdleSleepTimer(idleMilliSeconds);
3771 #endif
3772 } else if (!userIsActive) {
3773 // Manually start the idle sleep timer besides waiting for
3774 // the user to become inactive.
3775 startIdleSleepTimer(kIdleSleepRetryInterval);
3776 }
3777 }
3778
3779 preventTransitionToUserActive(false);
3780 IOService::setAdvisoryTickleEnable( true );
3781 idleSleepRevertible = true;
3782
3783 // After idle revert and cancel, send a did-change message to powerd
3784 // to balance the previous will-change message. Kernel clients do not
3785 // need this since sleep cannot be canceled once they are notified.
3786
3787 if (toldPowerdCapWillChange && systemCapabilityNotifier &&
3788 (_pendingCapability != _currentCapability) &&
3789 ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
3790 // Differs from a real capability gain change where notifyRef != 0,
3791 // but it is zero here since no response is expected.
3792
3793 IOPMSystemCapabilityChangeParameters params;
3794
3795 bzero(¶ms, sizeof(params));
3796 params.fromCapabilities = _pendingCapability;
3797 params.toCapabilities = _currentCapability;
3798 params.changeFlags = kIOPMSystemCapabilityDidChange;
3799
3800 DLOG("MESG cap %x->%x did change\n",
3801 params.fromCapabilities, params.toCapabilities);
3802 messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3803 ¶ms, sizeof(params));
3804 }
3805 }
3806
3807 //******************************************************************************
3808 // tellNoChangeDown
3809 //
3810 // Notify registered applications and kernel clients that we are not dropping
3811 // power.
3812 //
3813 // We override the superclass implementation so we can send a different message
3814 // type to the client or application being notified.
3815 //
3816 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3817 //******************************************************************************
3818
3819 void
tellNoChangeDown(unsigned long stateNum)3820 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3821 {
3822 DLOG("tellNoChangeDown %s->%s\n",
3823 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3824
3825 // Sleep canceled, clear the sleep trace point.
3826 tracePoint(kIOPMTracePointSystemUp);
3827
3828 systemDidNotSleep();
3829 return tellClients( kIOMessageSystemWillNotSleep );
3830 }
3831
3832 //******************************************************************************
3833 // tellChangeUp
3834 //
3835 // Notify registered applications and kernel clients that we are raising power.
3836 //
3837 // We override the superclass implementation so we can send a different message
3838 // type to the client or application being notified.
3839 //******************************************************************************
3840
3841 void
tellChangeUp(unsigned long stateNum)3842 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3843 {
3844 DLOG("tellChangeUp %s->%s\n",
3845 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3846
3847 ignoreTellChangeDown = false;
3848
3849 if (stateNum == ON_STATE) {
3850 // Direct callout into OSKext so it can disable kext unloads
3851 // during sleep/wake to prevent deadlocks.
3852 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3853
3854 // Notify platform that sleep was cancelled or resumed.
3855 getPlatform()->callPlatformFunction(
3856 sleepMessagePEFunction.get(), false,
3857 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3858 NULL, NULL, NULL);
3859
3860 if (getPowerState() == ON_STATE) {
3861 // Sleep was cancelled by idle cancel or revert
3862 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
3863 // rdar://problem/50363791
3864 // If system is in dark wake and sleep is cancelled, do not
3865 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3866 // priority clients. They haven't yet seen a SystemWillSleep
3867 // message before the cancellation. So make sure the kernel
3868 // client bit is cleared in _systemMessageClientMask before
3869 // invoking the tellClients() below. This bit may have been
3870 // set by handleOurPowerChangeStart() anticipating a successful
3871 // sleep and setting the filter mask ahead of time allows the
3872 // SystemWillSleep message to go through.
3873 _systemMessageClientMask &= ~kSystemMessageClientKernel;
3874 }
3875
3876 systemDidNotSleep();
3877 tellClients( kIOMessageSystemWillPowerOn );
3878 }
3879
3880 tracePoint( kIOPMTracePointWakeApplications );
3881 tellClients( kIOMessageSystemHasPoweredOn );
3882 } else if (stateNum == AOT_STATE) {
3883 if (getPowerState() == AOT_STATE) {
3884 // Sleep was cancelled by idle cancel or revert
3885 startIdleSleepTimer(idleMilliSeconds);
3886 }
3887 }
3888 }
3889
3890 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3891 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3892 ((params)->fromCapabilities & (flag)) && \
3893 (((params)->toCapabilities & (flag)) == 0))
3894
3895 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3896 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3897 ((params)->toCapabilities & (flag)) && \
3898 (((params)->fromCapabilities & (flag)) == 0))
3899
3900 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3901 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3902 ((params)->fromCapabilities & (flag)) && \
3903 (((params)->toCapabilities & (flag)) == 0))
3904
3905 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3906 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3907 ((params)->toCapabilities & (flag)) && \
3908 (((params)->fromCapabilities & (flag)) == 0))
3909
3910 //******************************************************************************
3911 // sysPowerDownHandler
3912 //
3913 // Perform a vfs sync before system sleep.
3914 //******************************************************************************
3915
3916 IOReturn
sysPowerDownHandler(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgs,vm_size_t argSize)3917 IOPMrootDomain::sysPowerDownHandler(
3918 void * target, void * refCon,
3919 UInt32 messageType, IOService * service,
3920 void * messageArgs, vm_size_t argSize )
3921 {
3922 static UInt32 lastSystemMessageType = 0;
3923 IOReturn ret = 0;
3924
3925 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3926
3927 // rdar://problem/50363791
3928 // Sanity check to make sure the SystemWill/Has message types are
3929 // received in the expected order for all kernel priority clients.
3930 if (messageType == kIOMessageSystemWillSleep ||
3931 messageType == kIOMessageSystemWillPowerOn ||
3932 messageType == kIOMessageSystemHasPoweredOn) {
3933 switch (messageType) {
3934 case kIOMessageSystemWillPowerOn:
3935 assert(lastSystemMessageType == kIOMessageSystemWillSleep);
3936 break;
3937 case kIOMessageSystemHasPoweredOn:
3938 assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3939 break;
3940 }
3941
3942 lastSystemMessageType = messageType;
3943 }
3944
3945 if (!gRootDomain) {
3946 return kIOReturnUnsupported;
3947 }
3948
3949 if (messageType == kIOMessageSystemCapabilityChange) {
3950 IOPMSystemCapabilityChangeParameters * params =
3951 (IOPMSystemCapabilityChangeParameters *) messageArgs;
3952
3953 // Interested applications have been notified of an impending power
3954 // change and have acked (when applicable).
3955 // This is our chance to save whatever state we can before powering
3956 // down.
3957 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3958 // via callout
3959
3960 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3961 params->fromCapabilities, params->toCapabilities,
3962 params->changeFlags);
3963
3964 if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3965 // We will ack within 20 seconds
3966 params->maxWaitForReply = 20 * 1000 * 1000;
3967
3968 #if HIBERNATION
3969 gRootDomain->evaluateSystemSleepPolicyEarly();
3970
3971 // add in time we could spend freeing pages
3972 if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3973 params->maxWaitForReply = kCapabilityClientMaxWait;
3974 }
3975 DLOG("sysPowerDownHandler max wait %d s\n",
3976 (int) (params->maxWaitForReply / 1000 / 1000));
3977 #endif
3978
3979 // Notify platform that sleep has begun, after the early
3980 // sleep policy evaluation.
3981 getPlatform()->callPlatformFunction(
3982 sleepMessagePEFunction.get(), false,
3983 (void *)(uintptr_t) kIOMessageSystemWillSleep,
3984 NULL, NULL, NULL);
3985
3986 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3987 // Purposely delay the ack and hope that shutdown occurs quickly.
3988 // Another option is not to schedule the thread and wait for
3989 // ack timeout...
3990 AbsoluteTime deadline;
3991 clock_interval_to_deadline( 30, kSecondScale, &deadline );
3992 thread_call_enter1_delayed(
3993 gRootDomain->diskSyncCalloutEntry,
3994 (thread_call_param_t)(uintptr_t) params->notifyRef,
3995 deadline );
3996 } else {
3997 thread_call_enter1(
3998 gRootDomain->diskSyncCalloutEntry,
3999 (thread_call_param_t)(uintptr_t) params->notifyRef);
4000 }
4001 }
4002 #if HIBERNATION
4003 else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
4004 // We will ack within 110 seconds
4005 params->maxWaitForReply = 110 * 1000 * 1000;
4006
4007 thread_call_enter1(
4008 gRootDomain->diskSyncCalloutEntry,
4009 (thread_call_param_t)(uintptr_t) params->notifyRef);
4010 }
4011 #endif
4012 ret = kIOReturnSuccess;
4013 }
4014
4015 return ret;
4016 }
4017
4018 //******************************************************************************
4019 // handleQueueSleepWakeUUID
4020 //
4021 // Called from IOPMrootDomain when we're initiating a sleep,
4022 // or indirectly from PM configd when PM decides to clear the UUID.
4023 // PM clears the UUID several minutes after successful wake from sleep,
4024 // so that we might associate App spindumps with the immediately previous
4025 // sleep/wake.
4026 //
4027 // @param obj has a retain on it. We're responsible for releasing that retain.
4028 //******************************************************************************
4029
4030 void
handleQueueSleepWakeUUID(OSObject * obj)4031 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
4032 {
4033 OSSharedPtr<OSString> str;
4034
4035 if (kOSBooleanFalse == obj) {
4036 handlePublishSleepWakeUUID(false);
4037 } else {
4038 str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
4039 if (str) {
4040 // This branch caches the UUID for an upcoming sleep/wake
4041 queuedSleepWakeUUIDString = str;
4042 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
4043 }
4044 }
4045 }
4046 //******************************************************************************
4047 // handlePublishSleepWakeUUID
4048 //
4049 // Called from IOPMrootDomain when we're initiating a sleep,
4050 // or indirectly from PM configd when PM decides to clear the UUID.
4051 // PM clears the UUID several minutes after successful wake from sleep,
4052 // so that we might associate App spindumps with the immediately previous
4053 // sleep/wake.
4054 //******************************************************************************
4055
4056 void
handlePublishSleepWakeUUID(bool shouldPublish)4057 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
4058 {
4059 ASSERT_GATED();
4060
4061 /*
4062 * Clear the current UUID
4063 */
4064 if (gSleepWakeUUIDIsSet) {
4065 DLOG("SleepWake UUID cleared\n");
4066
4067 gSleepWakeUUIDIsSet = false;
4068
4069 removeProperty(kIOPMSleepWakeUUIDKey);
4070 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
4071 }
4072
4073 /*
4074 * Optionally, publish a new UUID
4075 */
4076 if (queuedSleepWakeUUIDString && shouldPublish) {
4077 OSSharedPtr<OSString> publishThisUUID;
4078
4079 publishThisUUID = queuedSleepWakeUUIDString;
4080
4081 if (publishThisUUID) {
4082 setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
4083 }
4084
4085 gSleepWakeUUIDIsSet = true;
4086 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
4087
4088 queuedSleepWakeUUIDString.reset();
4089 }
4090 }
4091
4092 //******************************************************************************
4093 // IOPMGetSleepWakeUUIDKey
4094 //
4095 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
4096 // To get the full key -- a C string -- the buffer must large enough for
4097 // the end-of-string character.
4098 // The key is expected to be an UUID string
4099 //******************************************************************************
4100
4101 extern "C" bool
IOPMCopySleepWakeUUIDKey(char * buffer,size_t buf_len)4102 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
4103 {
4104 if (!gSleepWakeUUIDIsSet) {
4105 return false;
4106 }
4107
4108 if (buffer != NULL) {
4109 OSSharedPtr<OSString> string =
4110 OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
4111
4112 if (!string) {
4113 *buffer = '\0';
4114 } else {
4115 strlcpy(buffer, string->getCStringNoCopy(), buf_len);
4116 }
4117 }
4118
4119 return true;
4120 }
4121
4122 //******************************************************************************
4123 // lowLatencyAudioNotify
4124 //
4125 // Used to send an update about low latency audio activity to interested
4126 // clients. To keep the overhead minimal the OSDictionary used here
4127 // is initialized at boot.
4128 //******************************************************************************
4129
4130 void
lowLatencyAudioNotify(uint64_t time,boolean_t state)4131 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
4132 {
4133 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
4134 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
4135 lowLatencyAudioNotifyTimestampVal->setValue(time);
4136 lowLatencyAudioNotifyStateVal->setValue(state);
4137 setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
4138 } else {
4139 DLOG("LowLatencyAudioNotify error\n");
4140 }
4141 return;
4142 }
4143
4144 //******************************************************************************
4145 // IOPMrootDomainRTNotifier
4146 //
4147 // Used by performance controller to update the timestamp and state associated
4148 // with low latency audio activity in the system.
4149 //******************************************************************************
4150
4151 extern "C" void
IOPMrootDomainRTNotifier(uint64_t time,boolean_t state)4152 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
4153 {
4154 gRootDomain->lowLatencyAudioNotify(time, state);
4155 return;
4156 }
4157
4158 //******************************************************************************
4159 // initializeBootSessionUUID
4160 //
4161 // Initialize the boot session uuid at boot up and sets it into registry.
4162 //******************************************************************************
4163
4164 void
initializeBootSessionUUID(void)4165 IOPMrootDomain::initializeBootSessionUUID(void)
4166 {
4167 uuid_t new_uuid;
4168 uuid_string_t new_uuid_string;
4169
4170 uuid_generate(new_uuid);
4171 uuid_unparse_upper(new_uuid, new_uuid_string);
4172 memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
4173
4174 setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
4175 }
4176
4177 //******************************************************************************
4178 // Root domain uses the private and tagged changePowerState methods for
4179 // tracking and logging purposes.
4180 //******************************************************************************
4181
4182 #define REQUEST_TAG_TO_REASON(x) ((uint16_t)x)
4183
4184 static uint32_t
nextRequestTag(IOPMRequestTag tag)4185 nextRequestTag( IOPMRequestTag tag )
4186 {
4187 static SInt16 msb16 = 1;
4188 uint16_t id = OSAddAtomic16(1, &msb16);
4189 return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
4190 }
4191
4192 // TODO: remove this shim function and exported symbol
4193 IOReturn
changePowerStateTo(unsigned long ordinal)4194 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
4195 {
4196 return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
4197 }
4198
4199 // TODO: remove this shim function and exported symbol
4200 IOReturn
changePowerStateToPriv(unsigned long ordinal)4201 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
4202 {
4203 return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
4204 }
4205
4206 IOReturn
changePowerStateWithOverrideTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4207 IOPMrootDomain::changePowerStateWithOverrideTo(
4208 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4209 {
4210 uint32_t tag = nextRequestTag(reason);
4211 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4212
4213 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4214 return kIOReturnUnsupported;
4215 }
4216
4217 return super::changePowerStateWithOverrideTo(ordinal, tag);
4218 }
4219
4220 IOReturn
changePowerStateWithTagTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4221 IOPMrootDomain::changePowerStateWithTagTo(
4222 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4223 {
4224 uint32_t tag = nextRequestTag(reason);
4225 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4226
4227 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4228 return kIOReturnUnsupported;
4229 }
4230
4231 return super::changePowerStateWithTagTo(ordinal, tag);
4232 }
4233
4234 IOReturn
changePowerStateWithTagToPriv(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4235 IOPMrootDomain::changePowerStateWithTagToPriv(
4236 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4237 {
4238 uint32_t tag = nextRequestTag(reason);
4239 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4240
4241 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4242 return kIOReturnUnsupported;
4243 }
4244
4245 return super::changePowerStateWithTagToPriv(ordinal, tag);
4246 }
4247
4248 //******************************************************************************
4249 // activity detect
4250 //
4251 //******************************************************************************
4252
4253 bool
activitySinceSleep(void)4254 IOPMrootDomain::activitySinceSleep(void)
4255 {
4256 return userActivityCount != userActivityAtSleep;
4257 }
4258
4259 bool
abortHibernation(void)4260 IOPMrootDomain::abortHibernation(void)
4261 {
4262 #if __arm64__
4263 // don't allow hibernation to be aborted on ARM due to user activity
4264 // since once ApplePMGR decides we're hibernating, we can't turn back
4265 // see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4266 return false;
4267 #else
4268 bool ret = activitySinceSleep();
4269
4270 if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4271 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4272 hibernateAborted = true;
4273 }
4274 return ret;
4275 #endif
4276 }
4277
4278 extern "C" int
hibernate_should_abort(void)4279 hibernate_should_abort(void)
4280 {
4281 if (gRootDomain) {
4282 return gRootDomain->abortHibernation();
4283 } else {
4284 return 0;
4285 }
4286 }
4287
4288 //******************************************************************************
4289 // scheduleImmediateDebugWake
4290 //
4291 // Schedule a wake with RTC to wake us back up immediately after we sleep.
4292 // Useful when a cancel request comes in past the revert point on the sleep path
4293 //******************************************************************************
4294
4295 void
scheduleImmediateDebugWake(void)4296 IOPMrootDomain::scheduleImmediateDebugWake( void )
4297 {
4298 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(1);
4299 OSSharedPtr<OSNumber> secs = OSNumber::withNumber(1, 32);
4300
4301 if (dict && secs) {
4302 dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4303 gRootDomain->setProperties(dict.get());
4304 MSG("Reverting sleep with relative wake\n");
4305 }
4306 }
4307
4308 //******************************************************************************
4309 // willNotifyInterest
4310 //
4311 // Called after all priority clients have all acknowledged the power change,
4312 // but before any interested drivers and any power children are informed.
4313 // Dispatched though a thread call, so it is safe to perform work that might block on a
4314 // sleeping disk. PM state machine (not thread) will block w/o timeout until this function returns.
4315 //******************************************************************************
4316
4317 void
willNotifyInterested(IOPMPowerStateIndex newPowerState)4318 IOPMrootDomain::willNotifyInterested( IOPMPowerStateIndex newPowerState )
4319 {
4320 if (SLEEP_STATE == newPowerState) {
4321 _aotReadyToFullWake = false;
4322 #if 0
4323 if (_aotLingerTime) {
4324 uint64_t interval, deadline;
4325 IOLog("aot linger no return\n");
4326 nanoseconds_to_absolutetime(_aotLingerTime * NSEC_PER_MSEC, &interval);
4327 clock_absolutetime_interval_to_deadline(interval, &deadline);
4328 clock_delay_until(deadline);
4329 }
4330 #endif
4331 if (!_aotMode) {
4332 _aotTestTime = 0;
4333 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4334 _aotLastWakeTime = 0;
4335 if (_aotMetrics) {
4336 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4337 }
4338 } else if (!_aotNow && !_debugWakeSeconds) {
4339 _aotNow = true;
4340 _aotPendingFlags = 0;
4341 _aotTasksSuspended = true;
4342 _aotLastWakeTime = 0;
4343 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4344 if (kIOPMAOTModeCycle & _aotMode) {
4345 clock_interval_to_absolutetime_interval(10, kSecondScale, &_aotTestInterval);
4346 _aotTestTime = mach_continuous_time() + _aotTestInterval;
4347 AbsoluteTime endInterval;
4348 clock_interval_to_absolutetime_interval(60, kSecondScale, &endInterval);
4349 _aotEndTime = mach_continuous_time() + endInterval;
4350 _setWakeTime(_aotTestTime);
4351 }
4352 clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
4353 clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
4354 }
4355
4356 if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
4357 IOLog("PMRD: tasks suspend\n");
4358 AbsoluteTime deadline;
4359
4360 clock_interval_to_deadline(10, kSecondScale, &deadline);
4361 #if defined(XNU_TARGET_OS_OSX)
4362 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
4363 #endif /* defined(XNU_TARGET_OS_OSX) */
4364 }
4365 }
4366 }
4367
4368 //******************************************************************************
4369 // willNotifyPowerChildren
4370 //
4371 // Called after all interested drivers have all acknowledged the power change,
4372 // but before any power children are informed.
4373 // Dispatched though a thread call, so it is safe to perform work that might block on a
4374 // sleeping disk. PM state machine (not thread) will block w/o timeout until this function returns.
4375 //******************************************************************************
4376
4377 void
willNotifyPowerChildren(IOPMPowerStateIndex newPowerState)4378 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4379 {
4380 if (SLEEP_STATE == newPowerState) {
4381 notifierThread = current_thread();
4382
4383 #if HIBERNATION
4384 // Adjust watchdog for IOHibernateSystemSleep
4385 int defaultTimeout = getWatchdogTimeout();
4386 int timeout = defaultTimeout > WATCHDOG_HIBERNATION_TIMEOUT ?
4387 defaultTimeout : WATCHDOG_HIBERNATION_TIMEOUT;
4388 reset_watchdog_timer(timeout);
4389
4390 IOHibernateSystemSleep();
4391 IOHibernateIOKitSleep();
4392 #endif
4393 #if defined(__arm64__) && HIBERNATION
4394 if (gIOHibernateState == kIOHibernateStateInactive) {
4395 setProperty(kIOPMSystemSleepTypeKey, kIOPMSleepTypeDeepIdle, 32);
4396 }
4397 // On AS, hibernation cannot be aborted. Resetting RTC to 1s during hibernation upon detecting
4398 // user activity is pointless (we are likely to spend >1s hibernating). It also clears existing
4399 // alarms, which can mess with cycler tools.
4400 if (gRootDomain->activitySinceSleep() && gIOHibernateState == kIOHibernateStateInactive) {
4401 #else /* defined(__arm64__) && HIBERNATION */
4402 // On non-AS, hibernation can be aborted if user activity is detected. So continue to reset the
4403 // RTC alarm (even during hibernation) so we can immediately wake from regular S2R if needed.
4404 if (gRootDomain->activitySinceSleep()) {
4405 #endif /* defined(__arm64__) && HIBERNATION */
4406 scheduleImmediateDebugWake();
4407 }
4408
4409 notifierThread = NULL;
4410 }
4411 }
4412
4413 //******************************************************************************
4414 // willTellSystemCapabilityDidChange
4415 //
4416 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4417 // domain is raising its power state, immediately after notifying interested
4418 // drivers and power children.
4419 //******************************************************************************
4420
4421 void
4422 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4423 {
4424 if ((_systemTransitionType == kSystemTransitionWake) &&
4425 !CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
4426 // After powering up drivers, dark->full promotion on the current wake
4427 // transition is no longer possible. That is because the next machine
4428 // state will issue the system capability change messages.
4429 // The darkWakePowerClamped flag may already be set if the system has
4430 // at least one driver that was power clamped due to dark wake.
4431 // This function sets the darkWakePowerClamped flag in case there
4432 // is no power-clamped driver in the system.
4433 //
4434 // Last opportunity to exit dark wake using:
4435 // requestFullWake( kFullWakeReasonLocalUser );
4436
4437 if (!darkWakePowerClamped) {
4438 if (darkWakeLogClamp) {
4439 AbsoluteTime now;
4440 uint64_t nsec;
4441
4442 clock_get_uptime(&now);
4443 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
4444 absolutetime_to_nanoseconds(now, &nsec);
4445 DLOG("dark wake promotion disabled at %u ms\n",
4446 ((int)((nsec) / NSEC_PER_MSEC)));
4447 }
4448 darkWakePowerClamped = true;
4449 }
4450 }
4451 }
4452
4453 //******************************************************************************
4454 // sleepOnClamshellClosed
4455 //
4456 // contains the logic to determine if the system should sleep when the clamshell
4457 // is closed.
4458 //******************************************************************************
4459
4460 bool
4461 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4462 {
4463 if (!clamshellExists) {
4464 return false;
4465 }
4466
4467 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4468 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4469
4470 return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4471 }
4472
4473 bool
4474 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4475 {
4476 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4477 // closed && battery
4478 if (!clamshellExists) {
4479 return false;
4480 }
4481
4482 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4483 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4484
4485 return !acAdaptorConnected && !clamshellSleepDisableMask;
4486 }
4487
4488 void
4489 IOPMrootDomain::sendClientClamshellNotification( void )
4490 {
4491 /* Only broadcast clamshell alert if clamshell exists. */
4492 if (!clamshellExists) {
4493 return;
4494 }
4495
4496 setProperty(kAppleClamshellStateKey,
4497 clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4498
4499 setProperty(kAppleClamshellCausesSleepKey,
4500 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4501
4502 /* Argument to message is a bitfiel of
4503 * ( kClamshellStateBit | kClamshellSleepBit )
4504 */
4505 messageClients(kIOPMMessageClamshellStateChange,
4506 (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4507 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4508 }
4509
4510 //******************************************************************************
4511 // getSleepSupported
4512 //
4513 // Deprecated
4514 //******************************************************************************
4515
4516 IOOptionBits
4517 IOPMrootDomain::getSleepSupported( void )
4518 {
4519 return platformSleepSupport;
4520 }
4521
4522 //******************************************************************************
4523 // setSleepSupported
4524 //
4525 // Deprecated
4526 //******************************************************************************
4527
4528 void
4529 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4530 {
4531 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4532 OSBitOrAtomic(flags, &platformSleepSupport);
4533 }
4534
4535 //******************************************************************************
4536 // setClamShellSleepDisable
4537 //
4538 //******************************************************************************
4539
4540 void
4541 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4542 {
4543 uint32_t oldMask;
4544
4545 // User client calls this in non-gated context
4546 if (gIOPMWorkLoop->inGate() == false) {
4547 gIOPMWorkLoop->runAction(
4548 OSMemberFunctionCast(IOWorkLoop::Action, this,
4549 &IOPMrootDomain::setClamShellSleepDisable),
4550 (OSObject *) this,
4551 (void *) disable, (void *)(uintptr_t) bitmask);
4552 return;
4553 }
4554
4555 oldMask = clamshellSleepDisableMask;
4556 if (disable) {
4557 clamshellSleepDisableMask |= bitmask;
4558 } else {
4559 clamshellSleepDisableMask &= ~bitmask;
4560 }
4561 DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4562
4563 if (clamshellExists && clamshellClosed &&
4564 (clamshellSleepDisableMask != oldMask) &&
4565 (clamshellSleepDisableMask == 0)) {
4566 handlePowerNotification(kLocalEvalClamshellCommand);
4567 }
4568 }
4569
4570 //******************************************************************************
4571 // wakeFromDoze
4572 //
4573 // Deprecated.
4574 //******************************************************************************
4575
4576 void
4577 IOPMrootDomain::wakeFromDoze( void )
4578 {
4579 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4580 }
4581
4582 //******************************************************************************
4583 // recordRTCAlarm
4584 //
4585 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4586 // should be a dark wake or a full wake. Both Maintenance and SleepService
4587 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4588 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4589 // PMSettings are ignored.
4590 //
4591 // Caller serialized using settingsCtrlLock.
4592 //******************************************************************************
4593
4594 void
4595 IOPMrootDomain::recordRTCAlarm(
4596 const OSSymbol *type,
4597 OSObject *object )
4598 {
4599 uint32_t previousAlarmMask = _scheduledAlarmMask;
4600
4601 if (type == gIOPMSettingDebugWakeRelativeKey) {
4602 OSNumber * n = OSDynamicCast(OSNumber, object);
4603 if (n) {
4604 // Debug wake has highest scheduling priority so it overrides any
4605 // pre-existing alarm.
4606 uint32_t debugSecs = n->unsigned32BitValue();
4607 _nextScheduledAlarmType.reset(type, OSRetain);
4608 _nextScheduledAlarmUTC = debugSecs;
4609
4610 _debugWakeSeconds = debugSecs;
4611 OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4612 DLOG("next alarm (%s) in %u secs\n",
4613 type->getCStringNoCopy(), debugSecs);
4614 }
4615 } else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) ||
4616 (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) ||
4617 (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) {
4618 OSData * data = OSDynamicCast(OSData, object);
4619 if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) {
4620 const IOPMCalendarStruct * cs;
4621 bool replaceNextAlarm = false;
4622 clock_sec_t secs;
4623
4624 cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4625 secs = IOPMConvertCalendarToSeconds(cs);
4626 DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4627
4628 // Update the next scheduled alarm type
4629 if ((_nextScheduledAlarmType == NULL) ||
4630 ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4631 (secs < _nextScheduledAlarmUTC))) {
4632 replaceNextAlarm = true;
4633 }
4634
4635 if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4636 if (cs->year) {
4637 _calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4638 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4639 } else {
4640 // TODO: can this else-block be removed?
4641 _calendarWakeAlarmUTC = 0;
4642 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4643 }
4644 }
4645 if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4646 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4647 }
4648 if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4649 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4650 }
4651
4652 if (replaceNextAlarm) {
4653 _nextScheduledAlarmType.reset(type, OSRetain);
4654 _nextScheduledAlarmUTC = secs;
4655 DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4656 }
4657 }
4658 }
4659
4660 if (_scheduledAlarmMask != previousAlarmMask) {
4661 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4662 }
4663 }
4664
4665 // MARK: -
4666 // MARK: Features
4667
4668 //******************************************************************************
4669 // publishFeature
4670 //
4671 // Adds a new feature to the supported features dictionary
4672 //******************************************************************************
4673
4674 void
4675 IOPMrootDomain::publishFeature( const char * feature )
4676 {
4677 publishFeature(feature, kRD_AllPowerSources, NULL);
4678 }
4679
4680 //******************************************************************************
4681 // publishFeature (with supported power source specified)
4682 //
4683 // Adds a new feature to the supported features dictionary
4684 //******************************************************************************
4685
4686 void
4687 IOPMrootDomain::publishFeature(
4688 const char *feature,
4689 uint32_t supportedWhere,
4690 uint32_t *uniqueFeatureID)
4691 {
4692 static uint16_t next_feature_id = 500;
4693
4694 OSSharedPtr<OSNumber> new_feature_data;
4695 OSNumber *existing_feature = NULL;
4696 OSArray *existing_feature_arr_raw = NULL;
4697 OSSharedPtr<OSArray> existing_feature_arr;
4698 OSObject *osObj = NULL;
4699 uint32_t feature_value = 0;
4700
4701 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4702
4703 if (!supportedWhere) {
4704 // Feature isn't supported anywhere!
4705 return;
4706 }
4707
4708 if (next_feature_id > 5000) {
4709 // Far, far too many features!
4710 return;
4711 }
4712
4713 if (featuresDictLock) {
4714 IOLockLock(featuresDictLock);
4715 }
4716
4717 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4718 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4719 OSSharedPtr<OSDictionary> features;
4720
4721 // Create new features dict if necessary
4722 if (origFeatures) {
4723 features = OSDictionary::withDictionary(origFeatures);
4724 } else {
4725 features = OSDictionary::withCapacity(1);
4726 }
4727
4728 // Create OSNumber to track new feature
4729
4730 next_feature_id += 1;
4731 if (uniqueFeatureID) {
4732 // We don't really mind if the calling kext didn't give us a place
4733 // to stash their unique id. Many kexts don't plan to unload, and thus
4734 // have no need to remove themselves later.
4735 *uniqueFeatureID = next_feature_id;
4736 }
4737
4738 feature_value = (uint32_t)next_feature_id;
4739 feature_value <<= 16;
4740 feature_value += supportedWhere;
4741
4742 new_feature_data = OSNumber::withNumber(
4743 (unsigned long long)feature_value, 32);
4744
4745 // Does features object already exist?
4746 if ((osObj = features->getObject(feature))) {
4747 if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
4748 // We need to create an OSArray to hold the now 2 elements.
4749 existing_feature_arr = OSArray::withObjects(
4750 (const OSObject **)&existing_feature, 1, 2);
4751 } else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) {
4752 // Add object to existing array
4753 existing_feature_arr = OSArray::withArray(
4754 existing_feature_arr_raw,
4755 existing_feature_arr_raw->getCount() + 1);
4756 }
4757
4758 if (existing_feature_arr) {
4759 existing_feature_arr->setObject(new_feature_data.get());
4760 features->setObject(feature, existing_feature_arr.get());
4761 }
4762 } else {
4763 // The easy case: no previously existing features listed. We simply
4764 // set the OSNumber at key 'feature' and we're on our way.
4765 features->setObject(feature, new_feature_data.get());
4766 }
4767
4768 setProperty(kRootDomainSupportedFeatures, features.get());
4769
4770 if (featuresDictLock) {
4771 IOLockUnlock(featuresDictLock);
4772 }
4773
4774 // Notify EnergySaver and all those in user space so they might
4775 // re-populate their feature specific UI
4776 if (pmPowerStateQueue) {
4777 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4778 }
4779 }
4780
4781 //******************************************************************************
4782 // removePublishedFeature
4783 //
4784 // Removes previously published feature
4785 //******************************************************************************
4786
4787 IOReturn
4788 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4789 {
4790 IOReturn ret = kIOReturnError;
4791 uint32_t feature_value = 0;
4792 uint16_t feature_id = 0;
4793 bool madeAChange = false;
4794
4795 OSSymbol *dictKey = NULL;
4796 OSSharedPtr<OSCollectionIterator> dictIterator;
4797 OSArray *arrayMember = NULL;
4798 OSNumber *numberMember = NULL;
4799 OSObject *osObj = NULL;
4800 OSNumber *osNum = NULL;
4801 OSSharedPtr<OSArray> arrayMemberCopy;
4802
4803 if (kBadPMFeatureID == removeFeatureID) {
4804 return kIOReturnNotFound;
4805 }
4806
4807 if (featuresDictLock) {
4808 IOLockLock(featuresDictLock);
4809 }
4810
4811 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4812 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4813 OSSharedPtr<OSDictionary> features;
4814
4815 if (origFeatures) {
4816 // Any modifications to the dictionary are made to the copy to prevent
4817 // races & crashes with userland clients. Dictionary updated
4818 // automically later.
4819 features = OSDictionary::withDictionary(origFeatures);
4820 } else {
4821 features = NULL;
4822 ret = kIOReturnNotFound;
4823 goto exit;
4824 }
4825
4826 // We iterate 'features' dictionary looking for an entry tagged
4827 // with 'removeFeatureID'. If found, we remove it from our tracking
4828 // structures and notify the OS via a general interest message.
4829
4830 dictIterator = OSCollectionIterator::withCollection(features.get());
4831 if (!dictIterator) {
4832 goto exit;
4833 }
4834
4835 while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4836 osObj = features->getObject(dictKey);
4837
4838 // Each Feature is either tracked by an OSNumber
4839 if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
4840 feature_value = numberMember->unsigned32BitValue();
4841 feature_id = (uint16_t)(feature_value >> 16);
4842
4843 if (feature_id == (uint16_t)removeFeatureID) {
4844 // Remove this node
4845 features->removeObject(dictKey);
4846 madeAChange = true;
4847 break;
4848 }
4849
4850 // Or tracked by an OSArray of OSNumbers
4851 } else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4852 unsigned int arrayCount = arrayMember->getCount();
4853
4854 for (unsigned int i = 0; i < arrayCount; i++) {
4855 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4856 if (!osNum) {
4857 continue;
4858 }
4859
4860 feature_value = osNum->unsigned32BitValue();
4861 feature_id = (uint16_t)(feature_value >> 16);
4862
4863 if (feature_id == (uint16_t)removeFeatureID) {
4864 // Remove this node
4865 if (1 == arrayCount) {
4866 // If the array only contains one element, remove
4867 // the whole thing.
4868 features->removeObject(dictKey);
4869 } else {
4870 // Otherwise remove the element from a copy of the array.
4871 arrayMemberCopy = OSArray::withArray(arrayMember);
4872 if (arrayMemberCopy) {
4873 arrayMemberCopy->removeObject(i);
4874 features->setObject(dictKey, arrayMemberCopy.get());
4875 }
4876 }
4877
4878 madeAChange = true;
4879 break;
4880 }
4881 }
4882 }
4883 }
4884
4885 if (madeAChange) {
4886 ret = kIOReturnSuccess;
4887
4888 setProperty(kRootDomainSupportedFeatures, features.get());
4889
4890 // Notify EnergySaver and all those in user space so they might
4891 // re-populate their feature specific UI
4892 if (pmPowerStateQueue) {
4893 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4894 }
4895 } else {
4896 ret = kIOReturnNotFound;
4897 }
4898
4899 exit:
4900 if (featuresDictLock) {
4901 IOLockUnlock(featuresDictLock);
4902 }
4903 return ret;
4904 }
4905
4906 //******************************************************************************
4907 // publishPMSetting (private)
4908 //
4909 // Should only be called by PMSettingObject to publish a PM Setting as a
4910 // supported feature.
4911 //******************************************************************************
4912
4913 void
4914 IOPMrootDomain::publishPMSetting(
4915 const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4916 {
4917 if (noPublishPMSettings &&
4918 (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4919 // Setting found in noPublishPMSettings array
4920 *featureID = kBadPMFeatureID;
4921 return;
4922 }
4923
4924 publishFeature(
4925 feature->getCStringNoCopy(), where, featureID);
4926 }
4927
4928 //******************************************************************************
4929 // setPMSetting (private)
4930 //
4931 // Internal helper to relay PM settings changes from user space to individual
4932 // drivers. Should be called only by IOPMrootDomain::setProperties.
4933 //******************************************************************************
4934
4935 IOReturn
4936 IOPMrootDomain::setPMSetting(
4937 const OSSymbol *type,
4938 OSObject *object )
4939 {
4940 PMSettingCallEntry *entries = NULL;
4941 OSSharedPtr<OSArray> chosen;
4942 const OSArray *array;
4943 PMSettingObject *pmso;
4944 thread_t thisThread;
4945 int i, j, count, capacity;
4946 bool ok = false;
4947 IOReturn ret;
4948
4949 if (NULL == type) {
4950 return kIOReturnBadArgument;
4951 }
4952
4953 PMSETTING_LOCK();
4954
4955 // Update settings dict so changes are visible from copyPMSetting().
4956 fPMSettingsDict->setObject(type, object);
4957
4958 // Prep all PMSetting objects with the given 'type' for callout.
4959 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
4960 if (!array || ((capacity = array->getCount()) == 0)) {
4961 goto unlock_exit;
4962 }
4963
4964 // Array to retain PMSetting objects targeted for callout.
4965 chosen = OSArray::withCapacity(capacity);
4966 if (!chosen) {
4967 goto unlock_exit; // error
4968 }
4969 entries = IONew(PMSettingCallEntry, capacity);
4970 if (!entries) {
4971 goto unlock_exit; // error
4972 }
4973 memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4974
4975 thisThread = current_thread();
4976
4977 for (i = 0, j = 0; i < capacity; i++) {
4978 pmso = (PMSettingObject *) array->getObject(i);
4979 if (pmso->disabled) {
4980 continue;
4981 }
4982 entries[j].thread = thisThread;
4983 queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4984 chosen->setObject(pmso);
4985 j++;
4986 }
4987 count = j;
4988 if (!count) {
4989 goto unlock_exit;
4990 }
4991
4992 PMSETTING_UNLOCK();
4993
4994 // Call each pmso in the chosen array.
4995 for (i = 0; i < count; i++) {
4996 pmso = (PMSettingObject *) chosen->getObject(i);
4997 ret = pmso->dispatchPMSetting(type, object);
4998 if (ret == kIOReturnSuccess) {
4999 // At least one setting handler was successful
5000 ok = true;
5001 #if DEVELOPMENT || DEBUG
5002 } else {
5003 // Log the handler and kext that failed
5004 OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
5005 if (kextName) {
5006 DLOG("PMSetting(%s) error 0x%x from %s\n",
5007 type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
5008 }
5009 #endif
5010 }
5011 }
5012
5013 PMSETTING_LOCK();
5014 for (i = 0; i < count; i++) {
5015 pmso = (PMSettingObject *) chosen->getObject(i);
5016 queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
5017 if (pmso->waitThread) {
5018 PMSETTING_WAKEUP(pmso);
5019 }
5020 }
5021
5022 if (ok) {
5023 recordRTCAlarm(type, object);
5024 }
5025 unlock_exit:
5026 PMSETTING_UNLOCK();
5027
5028 if (entries) {
5029 IODelete(entries, PMSettingCallEntry, capacity);
5030 }
5031
5032 return kIOReturnSuccess;
5033 }
5034
5035 //******************************************************************************
5036 // copyPMSetting (public)
5037 //
5038 // Allows kexts to safely read setting values, without being subscribed to
5039 // notifications.
5040 //******************************************************************************
5041
5042 OSSharedPtr<OSObject>
5043 IOPMrootDomain::copyPMSetting(
5044 OSSymbol *whichSetting)
5045 {
5046 OSSharedPtr<OSObject> obj;
5047
5048 if (!whichSetting) {
5049 return NULL;
5050 }
5051
5052 PMSETTING_LOCK();
5053 obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
5054 PMSETTING_UNLOCK();
5055
5056 return obj;
5057 }
5058
5059 //******************************************************************************
5060 // registerPMSettingController (public)
5061 //
5062 // direct wrapper to registerPMSettingController with uint32_t power source arg
5063 //******************************************************************************
5064
5065 IOReturn
5066 IOPMrootDomain::registerPMSettingController(
5067 const OSSymbol * settings[],
5068 IOPMSettingControllerCallback func,
5069 OSObject *target,
5070 uintptr_t refcon,
5071 OSObject **handle)
5072 {
5073 return registerPMSettingController(
5074 settings,
5075 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
5076 func, target, refcon, handle);
5077 }
5078
5079 //******************************************************************************
5080 // registerPMSettingController (public)
5081 //
5082 // Kexts may register for notifications when a particular setting is changed.
5083 // A list of settings is available in IOPM.h.
5084 // Arguments:
5085 // * settings - An OSArray containing OSSymbols. Caller should populate this
5086 // array with a list of settings caller wants notifications from.
5087 // * func - A C function callback of the type IOPMSettingControllerCallback
5088 // * target - caller may provide an OSObject *, which PM will pass as an
5089 // target to calls to "func"
5090 // * refcon - caller may provide an void *, which PM will pass as an
5091 // argument to calls to "func"
5092 // * handle - This is a return argument. We will populate this pointer upon
5093 // call success. Hold onto this and pass this argument to
5094 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
5095 // Returns:
5096 // kIOReturnSuccess on success
5097 //******************************************************************************
5098
5099 IOReturn
5100 IOPMrootDomain::registerPMSettingController(
5101 const OSSymbol * settings[],
5102 uint32_t supportedPowerSources,
5103 IOPMSettingControllerCallback func,
5104 OSObject *target,
5105 uintptr_t refcon,
5106 OSObject **handle)
5107 {
5108 PMSettingObject *pmso = NULL;
5109 OSObject *pmsh = NULL;
5110 int i;
5111
5112 if (NULL == settings ||
5113 NULL == func ||
5114 NULL == handle) {
5115 return kIOReturnBadArgument;
5116 }
5117
5118 pmso = PMSettingObject::pmSettingObject(
5119 (IOPMrootDomain *) this, func, target,
5120 refcon, supportedPowerSources, settings, &pmsh);
5121
5122 if (!pmso) {
5123 *handle = NULL;
5124 return kIOReturnInternalError;
5125 }
5126
5127 PMSETTING_LOCK();
5128 for (i = 0; settings[i]; i++) {
5129 OSSharedPtr<OSArray> newList;
5130 OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
5131 if (!list) {
5132 // New array of callbacks for this setting
5133 newList = OSArray::withCapacity(1);
5134 settingsCallbacks->setObject(settings[i], newList.get());
5135 list = newList.get();
5136 }
5137
5138 // Add caller to the callback list
5139 list->setObject(pmso);
5140 }
5141 PMSETTING_UNLOCK();
5142
5143 // Return handle to the caller, the setting object is private.
5144 *handle = pmsh;
5145
5146 return kIOReturnSuccess;
5147 }
5148
5149 //******************************************************************************
5150 // deregisterPMSettingObject (private)
5151 //
5152 // Only called from PMSettingObject.
5153 //******************************************************************************
5154
5155 void
5156 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
5157 {
5158 thread_t thisThread = current_thread();
5159 PMSettingCallEntry *callEntry;
5160 OSSharedPtr<OSCollectionIterator> iter;
5161 OSSymbol *sym;
5162 OSArray *array;
5163 int index;
5164 bool wait;
5165
5166 PMSETTING_LOCK();
5167
5168 pmso->disabled = true;
5169
5170 // Wait for all callout threads to finish.
5171 do {
5172 wait = false;
5173 queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
5174 {
5175 if (callEntry->thread != thisThread) {
5176 wait = true;
5177 break;
5178 }
5179 }
5180 if (wait) {
5181 assert(NULL == pmso->waitThread);
5182 pmso->waitThread = thisThread;
5183 PMSETTING_WAIT(pmso);
5184 pmso->waitThread = NULL;
5185 }
5186 } while (wait);
5187
5188 // Search each PM settings array in the kernel.
5189 iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
5190 if (iter) {
5191 while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
5192 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
5193 index = array->getNextIndexOfObject(pmso, 0);
5194 if (-1 != index) {
5195 array->removeObject(index);
5196 }
5197 }
5198 }
5199
5200 PMSETTING_UNLOCK();
5201
5202 pmso->release();
5203 }
5204
5205 //******************************************************************************
5206 // informCPUStateChange
5207 //
5208 // Call into PM CPU code so that CPU power savings may dynamically adjust for
5209 // running on battery, with the lid closed, etc.
5210 //
5211 // informCPUStateChange is a no-op on non x86 systems
5212 // only x86 has explicit support in the IntelCPUPowerManagement kext
5213 //******************************************************************************
5214
5215 void
5216 IOPMrootDomain::informCPUStateChange(
5217 uint32_t type,
5218 uint32_t value )
5219 {
5220 #if defined(__i386__) || defined(__x86_64__)
5221
5222 pmioctlVariableInfo_t varInfoStruct;
5223 int pmCPUret = 0;
5224 const char *varNameStr = NULL;
5225 int32_t *varIndex = NULL;
5226
5227 if (kInformAC == type) {
5228 varNameStr = kIOPMRootDomainBatPowerCString;
5229 varIndex = &idxPMCPULimitedPower;
5230 } else if (kInformLid == type) {
5231 varNameStr = kIOPMRootDomainLidCloseCString;
5232 varIndex = &idxPMCPUClamshell;
5233 } else {
5234 return;
5235 }
5236
5237 // Set the new value!
5238 // pmCPUControl will assign us a new ID if one doesn't exist yet
5239 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
5240 varInfoStruct.varID = *varIndex;
5241 varInfoStruct.varType = vBool;
5242 varInfoStruct.varInitValue = value;
5243 varInfoStruct.varCurValue = value;
5244 strlcpy((char *)varInfoStruct.varName,
5245 (const char *)varNameStr,
5246 sizeof(varInfoStruct.varName));
5247
5248 // Set!
5249 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
5250
5251 // pmCPU only assigns numerical id's when a new varName is specified
5252 if ((0 == pmCPUret)
5253 && (*varIndex == kCPUUnknownIndex)) {
5254 // pmCPUControl has assigned us a new variable ID.
5255 // Let's re-read the structure we just SET to learn that ID.
5256 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
5257
5258 if (0 == pmCPUret) {
5259 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5260 *varIndex = varInfoStruct.varID;
5261 }
5262 }
5263
5264 return;
5265
5266 #endif /* __i386__ || __x86_64__ */
5267 }
5268
5269 // MARK: -
5270 // MARK: Deep Sleep Policy
5271
5272 #if HIBERNATION
5273
5274 //******************************************************************************
5275 // evaluateSystemSleepPolicy
5276 //******************************************************************************
5277
5278 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
5279
5280 // Sleep flags
5281 enum {
5282 kIOPMSleepFlagHibernate = 0x00000001,
5283 kIOPMSleepFlagSleepTimerEnable = 0x00000002
5284 };
5285
5286 struct IOPMSystemSleepPolicyEntry {
5287 uint32_t factorMask;
5288 uint32_t factorBits;
5289 uint32_t sleepFlags;
5290 uint32_t wakeEvents;
5291 } __attribute__((packed));
5292
5293 struct IOPMSystemSleepPolicyTable {
5294 uint32_t signature;
5295 uint16_t version;
5296 uint16_t entryCount;
5297 IOPMSystemSleepPolicyEntry entries[];
5298 } __attribute__((packed));
5299
5300 enum {
5301 kIOPMSleepAttributeHibernateSetup = 0x00000001,
5302 kIOPMSleepAttributeHibernateSleep = 0x00000002
5303 };
5304
5305 static uint32_t
5306 getSleepTypeAttributes( uint32_t sleepType )
5307 {
5308 static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5309 {
5310 /* invalid */ 0,
5311 /* abort */ 0,
5312 /* normal */ 0,
5313 /* safesleep */ kIOPMSleepAttributeHibernateSetup,
5314 /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5315 /* standby */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5316 /* poweroff */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5317 /* deepidle */ 0
5318 };
5319
5320 if (sleepType >= kIOPMSleepTypeLast) {
5321 return 0;
5322 }
5323
5324 return sleepTypeAttributes[sleepType];
5325 }
5326
5327 bool
5328 IOPMrootDomain::evaluateSystemSleepPolicy(
5329 IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5330 {
5331 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5332
5333 static const IONamedValue factorValues[] = {
5334 SLEEP_FACTOR( SleepTimerWake ),
5335 SLEEP_FACTOR( LidOpen ),
5336 SLEEP_FACTOR( ACPower ),
5337 SLEEP_FACTOR( BatteryLow ),
5338 SLEEP_FACTOR( StandbyNoDelay ),
5339 SLEEP_FACTOR( StandbyForced ),
5340 SLEEP_FACTOR( StandbyDisabled ),
5341 SLEEP_FACTOR( USBExternalDevice ),
5342 SLEEP_FACTOR( BluetoothHIDDevice ),
5343 SLEEP_FACTOR( ExternalMediaMounted ),
5344 SLEEP_FACTOR( ThunderboltDevice ),
5345 SLEEP_FACTOR( RTCAlarmScheduled ),
5346 SLEEP_FACTOR( MagicPacketWakeEnabled ),
5347 SLEEP_FACTOR( HibernateForced ),
5348 SLEEP_FACTOR( AutoPowerOffDisabled ),
5349 SLEEP_FACTOR( AutoPowerOffForced ),
5350 SLEEP_FACTOR( ExternalDisplay ),
5351 SLEEP_FACTOR( NetworkKeepAliveActive ),
5352 SLEEP_FACTOR( LocalUserActivity ),
5353 SLEEP_FACTOR( HibernateFailed ),
5354 SLEEP_FACTOR( ThermalWarning ),
5355 SLEEP_FACTOR( DisplayCaptured ),
5356 { 0, NULL }
5357 };
5358
5359 const IOPMSystemSleepPolicyTable * pt;
5360 OSSharedPtr<OSObject> prop;
5361 OSData * policyData;
5362 uint64_t currentFactors = 0;
5363 char currentFactorsBuf[512];
5364 uint32_t standbyDelay = 0;
5365 uint32_t powerOffDelay = 0;
5366 uint32_t powerOffTimer = 0;
5367 uint32_t standbyTimer = 0;
5368 uint32_t mismatch;
5369 bool standbyEnabled;
5370 bool powerOffEnabled;
5371 bool found = false;
5372
5373 // Get platform's sleep policy table
5374 if (!gSleepPolicyHandler) {
5375 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5376 if (!prop) {
5377 goto done;
5378 }
5379 }
5380
5381 // Fetch additional settings
5382 standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
5383 && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue));
5384 powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
5385 && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue));
5386 if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
5387 powerOffTimer = powerOffDelay;
5388 }
5389 if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5390 standbyTimer = standbyDelay;
5391 }
5392
5393 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5394 sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
5395 powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
5396
5397 currentFactorsBuf[0] = 0;
5398 // pmset level overrides
5399 if ((*hibMode & kIOHibernateModeOn) == 0) {
5400 if (!gSleepPolicyHandler) {
5401 standbyEnabled = false;
5402 powerOffEnabled = false;
5403 }
5404 } else if (!(*hibMode & kIOHibernateModeSleep)) {
5405 // Force hibernate (i.e. mode 25)
5406 // If standby is enabled, force standy.
5407 // If poweroff is enabled, force poweroff.
5408 if (standbyEnabled) {
5409 currentFactors |= kIOPMSleepFactorStandbyForced;
5410 } else if (powerOffEnabled) {
5411 currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
5412 } else {
5413 currentFactors |= kIOPMSleepFactorHibernateForced;
5414 }
5415 }
5416
5417 // Current factors based on environment and assertions
5418 if (sleepTimerMaintenance) {
5419 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5420 }
5421 if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5422 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5423 }
5424 if (!clamshellClosed) {
5425 currentFactors |= kIOPMSleepFactorLidOpen;
5426 }
5427 if (acAdaptorConnected) {
5428 currentFactors |= kIOPMSleepFactorACPower;
5429 }
5430 if (lowBatteryCondition) {
5431 hibernateMode = 0;
5432 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5433 if ((hibernateMode & kIOHibernateModeOn) == 0) {
5434 DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5435 } else {
5436 currentFactors |= kIOPMSleepFactorBatteryLow;
5437 }
5438 }
5439 if (!standbyDelay || !standbyTimer) {
5440 currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5441 }
5442 if (standbyNixed || !standbyEnabled) {
5443 currentFactors |= kIOPMSleepFactorStandbyDisabled;
5444 }
5445 if (resetTimers) {
5446 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5447 currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5448 }
5449 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5450 kIOPMDriverAssertionLevelOff) {
5451 currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5452 }
5453 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5454 kIOPMDriverAssertionLevelOff) {
5455 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5456 }
5457 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5458 kIOPMDriverAssertionLevelOff) {
5459 currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5460 }
5461 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5462 kIOPMDriverAssertionLevelOff) {
5463 currentFactors |= kIOPMSleepFactorThunderboltDevice;
5464 }
5465 if (_scheduledAlarmMask != 0) {
5466 currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5467 }
5468 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5469 kIOPMDriverAssertionLevelOff) {
5470 currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5471 }
5472 #define TCPKEEPALIVE 1
5473 #if TCPKEEPALIVE
5474 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5475 kIOPMDriverAssertionLevelOff) {
5476 currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5477 }
5478 #endif
5479 if (!powerOffEnabled) {
5480 currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5481 }
5482 if (desktopMode) {
5483 currentFactors |= kIOPMSleepFactorExternalDisplay;
5484 }
5485 if (userWasActive) {
5486 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5487 }
5488 if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5489 currentFactors |= kIOPMSleepFactorHibernateFailed;
5490 }
5491 if (thermalWarningState) {
5492 currentFactors |= kIOPMSleepFactorThermalWarning;
5493 }
5494
5495 for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) {
5496 uint32_t factor = 1 << factorBit;
5497 if (factor & currentFactors) {
5498 strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf));
5499 strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf));
5500 }
5501 }
5502 DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5503
5504 if (gSleepPolicyHandler) {
5505 uint32_t savedHibernateMode;
5506 IOReturn result;
5507
5508 if (!gSleepPolicyVars) {
5509 gSleepPolicyVars = IOMallocType(IOPMSystemSleepPolicyVariables);
5510 }
5511 gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
5512 gSleepPolicyVars->version = kIOPMSystemSleepPolicyVersion;
5513 gSleepPolicyVars->currentCapability = _currentCapability;
5514 gSleepPolicyVars->highestCapability = _highestCapability;
5515 gSleepPolicyVars->sleepFactors = currentFactors;
5516 gSleepPolicyVars->sleepReason = lastSleepReason;
5517 gSleepPolicyVars->sleepPhase = sleepPhase;
5518 gSleepPolicyVars->standbyDelay = standbyDelay;
5519 gSleepPolicyVars->standbyTimer = standbyTimer;
5520 gSleepPolicyVars->poweroffDelay = powerOffDelay;
5521 gSleepPolicyVars->scheduledAlarms = _scheduledAlarmMask | _userScheduledAlarmMask;
5522 gSleepPolicyVars->poweroffTimer = powerOffTimer;
5523
5524 if (kIOPMSleepPhase0 == sleepPhase) {
5525 // preserve hibernateMode
5526 savedHibernateMode = gSleepPolicyVars->hibernateMode;
5527 gSleepPolicyVars->hibernateMode = *hibMode;
5528 } else if (kIOPMSleepPhase1 == sleepPhase) {
5529 // use original hibernateMode for phase2
5530 gSleepPolicyVars->hibernateMode = *hibMode;
5531 }
5532
5533 result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5534
5535 if (kIOPMSleepPhase0 == sleepPhase) {
5536 // restore hibernateMode
5537 gSleepPolicyVars->hibernateMode = savedHibernateMode;
5538 }
5539
5540 if ((result != kIOReturnSuccess) ||
5541 (kIOPMSleepTypeInvalid == params->sleepType) ||
5542 (params->sleepType >= kIOPMSleepTypeLast) ||
5543 (kIOPMSystemSleepParametersVersion != params->version)) {
5544 MSG("sleep policy handler error\n");
5545 goto done;
5546 }
5547
5548 if ((getSleepTypeAttributes(params->sleepType) &
5549 kIOPMSleepAttributeHibernateSetup) &&
5550 ((*hibMode & kIOHibernateModeOn) == 0)) {
5551 *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5552 }
5553
5554 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5555 params->version, params->sleepType, params->sleepFlags,
5556 params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
5557 found = true;
5558 goto done;
5559 }
5560
5561 // Policy table is meaningless without standby enabled
5562 if (!standbyEnabled) {
5563 goto done;
5564 }
5565
5566 // Validate the sleep policy table
5567 policyData = OSDynamicCast(OSData, prop.get());
5568 if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5569 goto done;
5570 }
5571
5572 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5573 if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5574 (pt->version != 1) || (0 == pt->entryCount)) {
5575 goto done;
5576 }
5577
5578 if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5579 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5580 goto done;
5581 }
5582
5583 for (uint32_t i = 0; i < pt->entryCount; i++) {
5584 const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
5585 mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
5586
5587 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5588 entry->factorMask, entry->factorBits,
5589 entry->sleepFlags, entry->wakeEvents, mismatch);
5590 if (mismatch) {
5591 continue;
5592 }
5593
5594 DLOG("^ found match\n");
5595 found = true;
5596
5597 params->version = kIOPMSystemSleepParametersVersion;
5598 params->reserved1 = 1;
5599 if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5600 params->sleepType = kIOPMSleepTypeStandby;
5601 } else {
5602 params->sleepType = kIOPMSleepTypeNormalSleep;
5603 }
5604
5605 params->ecWakeEvents = entry->wakeEvents;
5606 if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5607 if (kIOPMSleepPhase2 == sleepPhase) {
5608 clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5609
5610 if (!_standbyTimerResetSeconds ||
5611 (now_secs <= _standbyTimerResetSeconds)) {
5612 // Reset standby timer adjustment
5613 _standbyTimerResetSeconds = now_secs;
5614 DLOG("standby delay %u, reset %u\n",
5615 standbyDelay, (uint32_t) _standbyTimerResetSeconds);
5616 } else if (standbyDelay) {
5617 // Shorten the standby delay timer
5618 clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
5619 if (standbyDelay > elapsed) {
5620 standbyDelay -= elapsed;
5621 } else {
5622 standbyDelay = 1; // must be > 0
5623 }
5624 DLOG("standby delay %u, elapsed %u\n",
5625 standbyDelay, (uint32_t) elapsed);
5626 }
5627 }
5628 params->ecWakeTimer = standbyDelay;
5629 } else if (kIOPMSleepPhase2 == sleepPhase) {
5630 // A sleep that does not enable the sleep timer will reset
5631 // the standby delay adjustment.
5632 _standbyTimerResetSeconds = 0;
5633 }
5634 break;
5635 }
5636
5637 done:
5638 return found;
5639 }
5640
5641 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5642
5643 void
5644 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5645 {
5646 // Evaluate early (priority interest phase), before drivers sleep.
5647
5648 DLOG("%s\n", __FUNCTION__);
5649 removeProperty(kIOPMSystemSleepParametersKey);
5650
5651 // Full wake resets the standby timer delay adjustment
5652 if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5653 _standbyTimerResetSeconds = 0;
5654 }
5655
5656 hibernateDisabled = false;
5657 hibernateMode = 0;
5658 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5659
5660 // Save for late evaluation if sleep is aborted
5661 bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5662
5663 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5664 &hibernateMode)) {
5665 if (!hibernateRetry &&
5666 ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5667 kIOPMSleepAttributeHibernateSetup) == 0)) {
5668 // skip hibernate setup
5669 hibernateDisabled = true;
5670 }
5671 }
5672
5673 // Publish IOPMSystemSleepType
5674 uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5675 if (sleepType == kIOPMSleepTypeInvalid) {
5676 // no sleep policy
5677 sleepType = kIOPMSleepTypeNormalSleep;
5678 if (hibernateMode & kIOHibernateModeOn) {
5679 sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5680 kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5681 }
5682 } else if ((sleepType == kIOPMSleepTypeStandby) &&
5683 (gEarlySystemSleepParams.ecPoweroffTimer)) {
5684 // report the lowest possible sleep state
5685 sleepType = kIOPMSleepTypePowerOff;
5686 }
5687
5688 setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5689 }
5690
5691 void
5692 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5693 {
5694 IOPMSystemSleepParameters params;
5695 OSSharedPtr<OSData> paramsData;
5696 bool wakeNow;
5697 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5698
5699 DLOG("%s\n", __FUNCTION__);
5700
5701 bzero(¶ms, sizeof(params));
5702 wakeNow = false;
5703 if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2, &hibernateMode)) {
5704 if ((kIOPMSleepTypeStandby == params.sleepType)
5705 && gIOHibernateStandbyDisabled && gSleepPolicyVars
5706 && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5707 & gSleepPolicyVars->sleepFactors))) {
5708 standbyNixed = true;
5709 wakeNow = true;
5710 }
5711 if (wakeNow
5712 || ((hibernateDisabled || hibernateAborted) &&
5713 (getSleepTypeAttributes(params.sleepType) &
5714 kIOPMSleepAttributeHibernateSetup))) {
5715 // Final evaluation picked a state requiring hibernation,
5716 // but hibernate isn't going to proceed. Arm a short sleep using
5717 // the early non-hibernate sleep parameters.
5718 bcopy(&gEarlySystemSleepParams, ¶ms, sizeof(params));
5719 params.sleepType = kIOPMSleepTypeAbortedSleep;
5720 params.ecWakeTimer = 1;
5721 if (standbyNixed) {
5722 resetTimers = true;
5723 } else {
5724 // Set hibernateRetry flag to force hibernate setup on the
5725 // next sleep.
5726 hibernateRetry = true;
5727 }
5728 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5729 params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5730 } else {
5731 hibernateRetry = false;
5732 }
5733
5734 if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5735 resetTimers = false;
5736 }
5737
5738 paramsData = OSData::withValue(params);
5739 if (paramsData) {
5740 setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5741 }
5742
5743 if (getSleepTypeAttributes(params.sleepType) &
5744 kIOPMSleepAttributeHibernateSleep) {
5745 // Disable sleep to force hibernation
5746 gIOHibernateMode &= ~kIOHibernateModeSleep;
5747 }
5748 }
5749 }
5750
5751 bool
5752 IOPMrootDomain::getHibernateSettings(
5753 uint32_t * hibernateModePtr,
5754 uint32_t * hibernateFreeRatio,
5755 uint32_t * hibernateFreeTime )
5756 {
5757 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5758 // has updated the hibernateDisabled flag.
5759
5760 bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
5761 getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
5762 getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
5763 if (hibernateDisabled) {
5764 *hibernateModePtr = 0;
5765 } else if (gSleepPolicyHandler) {
5766 *hibernateModePtr = hibernateMode;
5767 }
5768 DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5769 return ok;
5770 }
5771
5772 bool
5773 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5774 {
5775 OSSharedPtr<OSObject> optionsProp;
5776 OSDictionary * optionsDict;
5777 OSSharedPtr<OSObject> obj;
5778 OSNumber * num;
5779 bool ok = false;
5780
5781 optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5782 optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5783
5784 if (optionsDict) {
5785 obj.reset(optionsDict->getObject(key), OSRetain);
5786 }
5787 if (!obj) {
5788 obj = copyProperty(key);
5789 }
5790 if (obj) {
5791 if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5792 *option = num->unsigned32BitValue();
5793 ok = true;
5794 } else if (OSDynamicCast(OSBoolean, obj.get())) {
5795 *option = (obj == kOSBooleanTrue) ? 1 : 0;
5796 ok = true;
5797 }
5798 }
5799
5800 return ok;
5801 }
5802 #endif /* HIBERNATION */
5803
5804 IOReturn
5805 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5806 {
5807 #if HIBERNATION
5808 IOPMSystemSleepParameters params;
5809 uint32_t hibMode = 0;
5810 bool ok;
5811
5812 if (gIOPMWorkLoop->inGate() == false) {
5813 IOReturn ret = gIOPMWorkLoop->runAction(
5814 OSMemberFunctionCast(IOWorkLoop::Action, this,
5815 &IOPMrootDomain::getSystemSleepType),
5816 (OSObject *) this,
5817 (void *) sleepType, (void *) standbyTimer);
5818 return ret;
5819 }
5820
5821 getSleepOption(kIOHibernateModeKey, &hibMode);
5822 bzero(¶ms, sizeof(params));
5823
5824 ok = evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase0, &hibMode);
5825 if (ok) {
5826 *sleepType = params.sleepType;
5827 if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5828 !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5829 DLOG("Standby delay is not set\n");
5830 *standbyTimer = 0;
5831 }
5832 return kIOReturnSuccess;
5833 }
5834 #endif
5835
5836 return kIOReturnUnsupported;
5837 }
5838
5839 // MARK: -
5840 // MARK: Shutdown and Restart
5841
5842 //******************************************************************************
5843 // handlePlatformHaltRestart
5844 //
5845 //******************************************************************************
5846
5847 // Phases while performing shutdown/restart
5848 typedef enum {
5849 kNotifyDone = 0x00,
5850 kNotifyPriorityClients = 0x10,
5851 kNotifyPowerPlaneDrivers = 0x20,
5852 kNotifyHaltRestartAction = 0x30,
5853 kQuiescePM = 0x40,
5854 } shutdownPhase_t;
5855
5856
5857 struct HaltRestartApplierContext {
5858 IOPMrootDomain * RootDomain;
5859 unsigned long PowerState;
5860 IOPMPowerFlags PowerFlags;
5861 UInt32 MessageType;
5862 UInt32 Counter;
5863 const char * LogString;
5864 shutdownPhase_t phase;
5865
5866 IOServiceInterestHandler handler;
5867 } gHaltRestartCtx;
5868
5869 const char *
5870 shutdownPhase2String(shutdownPhase_t phase)
5871 {
5872 switch (phase) {
5873 case kNotifyDone:
5874 return "Notifications completed";
5875 case kNotifyPriorityClients:
5876 return "Notifying priority clients";
5877 case kNotifyPowerPlaneDrivers:
5878 return "Notifying power plane drivers";
5879 case kNotifyHaltRestartAction:
5880 return "Notifying HaltRestart action handlers";
5881 case kQuiescePM:
5882 return "Quiescing PM";
5883 default:
5884 return "Unknown";
5885 }
5886 }
5887
5888 static void
5889 platformHaltRestartApplier( OSObject * object, void * context )
5890 {
5891 IOPowerStateChangeNotification notify;
5892 HaltRestartApplierContext * ctx;
5893 AbsoluteTime startTime, elapsedTime;
5894 uint32_t deltaTime;
5895
5896 ctx = (HaltRestartApplierContext *) context;
5897
5898 _IOServiceInterestNotifier * notifier;
5899 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5900 memset(¬ify, 0, sizeof(notify));
5901 notify.powerRef = (void *)(uintptr_t)ctx->Counter;
5902 notify.returnValue = 0;
5903 notify.stateNumber = ctx->PowerState;
5904 notify.stateFlags = ctx->PowerFlags;
5905
5906 if (notifier) {
5907 ctx->handler = notifier->handler;
5908 }
5909
5910 clock_get_uptime(&startTime);
5911 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)¬ify );
5912 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5913
5914 if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
5915 LOG("%s handler %p took %u ms\n",
5916 ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
5917 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
5918 }
5919
5920 ctx->handler = NULL;
5921 ctx->Counter++;
5922 }
5923
5924 static void
5925 quiescePowerTreeCallback( void * target, void * param )
5926 {
5927 IOLockLock(gPMHaltLock);
5928 gPMQuiesced = true;
5929 thread_wakeup(param);
5930 IOLockUnlock(gPMHaltLock);
5931 }
5932
5933 void
5934 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5935 {
5936 AbsoluteTime startTime, elapsedTime;
5937 uint32_t deltaTime;
5938 bool nvramSync = false;
5939
5940 memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5941 gHaltRestartCtx.RootDomain = this;
5942
5943 clock_get_uptime(&startTime);
5944 switch (pe_type) {
5945 case kPEHaltCPU:
5946 case kPEUPSDelayHaltCPU:
5947 gHaltRestartCtx.PowerState = OFF_STATE;
5948 gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5949 gHaltRestartCtx.LogString = "PowerOff";
5950 nvramSync = true;
5951 break;
5952
5953 case kPERestartCPU:
5954 gHaltRestartCtx.PowerState = RESTART_STATE;
5955 gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5956 gHaltRestartCtx.LogString = "Restart";
5957 nvramSync = true;
5958 break;
5959
5960 case kPEPagingOff:
5961 gHaltRestartCtx.PowerState = ON_STATE;
5962 gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5963 gHaltRestartCtx.LogString = "PagingOff";
5964 IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5965 #if HIBERNATION
5966 IOHibernateSystemRestart();
5967 #endif
5968 break;
5969
5970 default:
5971 return;
5972 }
5973
5974 if (nvramSync) {
5975 PESyncNVRAM();
5976 }
5977
5978 gHaltRestartCtx.phase = kNotifyPriorityClients;
5979 // Notify legacy clients
5980 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5981
5982 // For normal shutdown, turn off File Server Mode.
5983 if (kPEHaltCPU == pe_type) {
5984 OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
5985 OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32);
5986 if (setting && num) {
5987 setPMSetting(setting.get(), num.get());
5988 }
5989 }
5990
5991 if (kPEPagingOff != pe_type) {
5992 gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5993 // Notify in power tree order
5994 notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5995 }
5996
5997 gHaltRestartCtx.phase = kNotifyHaltRestartAction;
5998 #if defined(XNU_TARGET_OS_OSX)
5999 IOCPURunPlatformHaltRestartActions(pe_type);
6000 #else /* !defined(XNU_TARGET_OS_OSX) */
6001 if (kPEPagingOff != pe_type) {
6002 IOCPURunPlatformHaltRestartActions(pe_type);
6003 }
6004 #endif /* !defined(XNU_TARGET_OS_OSX) */
6005
6006 // Wait for PM to quiesce
6007 if ((kPEPagingOff != pe_type) && gPMHaltLock) {
6008 gHaltRestartCtx.phase = kQuiescePM;
6009 AbsoluteTime quiesceTime = mach_absolute_time();
6010
6011 IOLockLock(gPMHaltLock);
6012 gPMQuiesced = false;
6013 if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
6014 kIOReturnSuccess) {
6015 while (!gPMQuiesced) {
6016 IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
6017 }
6018 }
6019 IOLockUnlock(gPMHaltLock);
6020 deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
6021 DLOG("PM quiesce took %u ms\n", deltaTime);
6022 halt_log_enter("Quiesce", NULL, elapsedTime);
6023 }
6024 gHaltRestartCtx.phase = kNotifyDone;
6025
6026 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
6027 LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
6028
6029 halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
6030
6031 deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
6032 LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
6033
6034 if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
6035 printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
6036 }
6037
6038 checkShutdownTimeout();
6039 }
6040
6041 bool
6042 IOPMrootDomain::checkShutdownTimeout()
6043 {
6044 AbsoluteTime elapsedTime;
6045 uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
6046
6047 if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
6048 return true;
6049 }
6050 return false;
6051 }
6052
6053 void
6054 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
6055 {
6056 if (gHaltLog) {
6057 if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
6058 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
6059 }
6060 panic("%s timed out in phase '%s'. Total %d ms:%s",
6061 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
6062 } else {
6063 panic("%s timed out in phase \'%s\'. Total %d ms",
6064 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
6065 }
6066 }
6067
6068 //******************************************************************************
6069 // shutdownSystem
6070 //
6071 //******************************************************************************
6072
6073 IOReturn
6074 IOPMrootDomain::shutdownSystem( void )
6075 {
6076 return kIOReturnUnsupported;
6077 }
6078
6079 //******************************************************************************
6080 // restartSystem
6081 //
6082 //******************************************************************************
6083
6084 IOReturn
6085 IOPMrootDomain::restartSystem( void )
6086 {
6087 return kIOReturnUnsupported;
6088 }
6089
6090 // MARK: -
6091 // MARK: System Capability
6092
6093 //******************************************************************************
6094 // tagPowerPlaneService
6095 //
6096 // Running on PM work loop thread.
6097 //******************************************************************************
6098
6099 void
6100 IOPMrootDomain::tagPowerPlaneService(
6101 IOService * service,
6102 IOPMActions * actions,
6103 IOPMPowerStateIndex maxPowerState )
6104 {
6105 uint32_t flags = 0;
6106
6107 memset(actions, 0, sizeof(*actions));
6108 actions->target = this;
6109
6110 if (service == this) {
6111 actions->actionPowerChangeStart =
6112 OSMemberFunctionCast(
6113 IOPMActionPowerChangeStart, this,
6114 &IOPMrootDomain::handleOurPowerChangeStart);
6115
6116 actions->actionPowerChangeDone =
6117 OSMemberFunctionCast(
6118 IOPMActionPowerChangeDone, this,
6119 &IOPMrootDomain::handleOurPowerChangeDone);
6120
6121 actions->actionPowerChangeOverride =
6122 OSMemberFunctionCast(
6123 IOPMActionPowerChangeOverride, this,
6124 &IOPMrootDomain::overrideOurPowerChange);
6125 return;
6126 }
6127
6128 #if DISPLAY_WRANGLER_PRESENT
6129 if (NULL != service->metaCast("IODisplayWrangler")) {
6130 // XXX should this really retain?
6131 wrangler.reset(service, OSRetain);
6132 wrangler->registerInterest(gIOGeneralInterest,
6133 &displayWranglerNotification, this, NULL);
6134
6135 // found the display wrangler, check for any display assertions already created
6136 if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
6137 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
6138 wrangler->setIgnoreIdleTimer( true );
6139 }
6140 flags |= kPMActionsFlagIsDisplayWrangler;
6141 }
6142 #endif /* DISPLAY_WRANGLER_PRESENT */
6143
6144 if (service->propertyExists("IOPMStrictTreeOrder")) {
6145 flags |= kPMActionsFlagIsGraphicsDriver;
6146 }
6147 if (service->propertyExists("IOPMUnattendedWakePowerState")) {
6148 flags |= kPMActionsFlagIsAudioDriver;
6149 }
6150
6151 // Find the power connection object that is a child of the PCI host
6152 // bridge, and has a graphics/audio device attached below. Mark the
6153 // power branch for delayed child notifications.
6154
6155 if (flags) {
6156 IORegistryEntry * child = service;
6157 IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
6158
6159 while (child != this) {
6160 if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) {
6161 // Skip delaying notifications and clamping power on external graphics and audio devices.
6162 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
6163 flags = 0;
6164 break;
6165 }
6166 if ((parent == pciHostBridgeDriver) ||
6167 (parent == this)) {
6168 if (OSDynamicCast(IOPowerConnection, child)) {
6169 IOPowerConnection * conn = (IOPowerConnection *) child;
6170 conn->delayChildNotification = true;
6171 DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
6172 }
6173 break;
6174 }
6175 child = parent;
6176 parent = child->getParentEntry(gIOPowerPlane);
6177 }
6178 }
6179
6180 OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
6181 if (prop) {
6182 OSNumber * num = OSDynamicCast(OSNumber, prop.get());
6183 if (num) {
6184 actions->darkWakePowerState = num->unsigned32BitValue();
6185 if (actions->darkWakePowerState < maxPowerState) {
6186 flags |= kPMActionsFlagHasDarkWakePowerState;
6187 }
6188 }
6189 }
6190
6191
6192 if (flags) {
6193 DLOG("%s tag flags %x\n", service->getName(), flags);
6194 actions->flags |= flags;
6195 actions->actionPowerChangeOverride =
6196 OSMemberFunctionCast(
6197 IOPMActionPowerChangeOverride, this,
6198 &IOPMrootDomain::overridePowerChangeForService);
6199
6200 if (flags & kPMActionsFlagIsDisplayWrangler) {
6201 actions->actionActivityTickle =
6202 OSMemberFunctionCast(
6203 IOPMActionActivityTickle, this,
6204 &IOPMrootDomain::handleActivityTickleForDisplayWrangler);
6205
6206 actions->actionUpdatePowerClient =
6207 OSMemberFunctionCast(
6208 IOPMActionUpdatePowerClient, this,
6209 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
6210 }
6211 return;
6212 }
6213
6214 // Locate the first PCI host bridge for PMTrace.
6215 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
6216 IOService * provider = service->getProvider();
6217 if (OSDynamicCast(IOPlatformDevice, provider) &&
6218 provider->inPlane(gIODTPlane)) {
6219 pciHostBridgeDevice.reset(provider, OSNoRetain);
6220 pciHostBridgeDriver.reset(service, OSNoRetain);
6221 DLOG("PMTrace found PCI host bridge %s->%s\n",
6222 provider->getName(), service->getName());
6223 }
6224 }
6225
6226 // Tag top-level PCI devices. The order of PMinit() call does not
6227 // change across boots and is used as the PCI bit number.
6228 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
6229 // Would prefer to check built-in property, but tagPowerPlaneService()
6230 // is called before pciDevice->registerService().
6231 IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
6232 if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) {
6233 int bit = pmTracer->recordTopLevelPCIDevice( service );
6234 if (bit >= 0) {
6235 // Save the assigned bit for fast lookup.
6236 actions->flags |= (bit & kPMActionsPCIBitNumberMask);
6237
6238 actions->actionPowerChangeStart =
6239 OSMemberFunctionCast(
6240 IOPMActionPowerChangeStart, this,
6241 &IOPMrootDomain::handlePowerChangeStartForPCIDevice);
6242
6243 actions->actionPowerChangeDone =
6244 OSMemberFunctionCast(
6245 IOPMActionPowerChangeDone, this,
6246 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
6247 }
6248 }
6249 }
6250 }
6251
6252 //******************************************************************************
6253 // PM actions for root domain
6254 //******************************************************************************
6255
6256 void
6257 IOPMrootDomain::overrideOurPowerChange(
6258 IOService * service,
6259 IOPMActions * actions,
6260 const IOPMRequest * request,
6261 IOPMPowerStateIndex * inOutPowerState,
6262 IOPMPowerChangeFlags * inOutChangeFlags )
6263 {
6264 uint32_t changeFlags = *inOutChangeFlags;
6265 uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
6266 uint32_t currentPowerState = (uint32_t) getPowerState();
6267
6268 if (request->getTag() == 0) {
6269 // Set a tag for any request that originates from IOServicePM
6270 (const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
6271 }
6272
6273 DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6274 getPowerStateString(currentPowerState),
6275 getPowerStateString(desiredPowerState),
6276 _currentCapability, changeFlags,
6277 request->getTag());
6278
6279
6280 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6281 /*
6282 * ASBM send lowBattery notifications every 1 second until the device
6283 * enters hibernation. This queues up multiple sleep requests.
6284 * After the device wakes from hibernation, none of these previously
6285 * queued sleep requests are valid.
6286 * lowBattteryCondition variable is set when ASBM notifies rootDomain
6287 * and is cleared at the very last point in sleep.
6288 * Any attempt to sleep with reason kIOPMSleepReasonLowPower without
6289 * lowBatteryCondition is invalid
6290 */
6291 if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) {
6292 if (!lowBatteryCondition) {
6293 DLOG("Duplicate lowBattery sleep");
6294 *inOutChangeFlags |= kIOPMNotDone;
6295 return;
6296 }
6297 }
6298 #endif
6299
6300 if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
6301 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6302 *inOutChangeFlags |= kIOPMNotDone;
6303 return;
6304 }
6305
6306 if (changeFlags & kIOPMParentInitiated) {
6307 // Root parent is permanently pegged at max power,
6308 // a parent initiated power change is unexpected.
6309 *inOutChangeFlags |= kIOPMNotDone;
6310 return;
6311 }
6312
6313 #if HIBERNATION && defined(__arm64__)
6314 if (lowBatteryCondition && (desiredPowerState < currentPowerState)) {
6315 if (!ml_is_secure_hib_supported() || ldmHibernateDisable) {
6316 // If hibernation is unsupported, reject sleep requests to avoid
6317 // racing with system shutdown.
6318 *inOutChangeFlags |= kIOPMNotDone;
6319 return;
6320 }
6321 }
6322 #endif /* HIBERNATION && defined(__arm64__) */
6323
6324 if (desiredPowerState < currentPowerState) {
6325 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6326 // Root domain is dropping power state from ON->SLEEP.
6327 // If system is in full wake, first enter dark wake by
6328 // converting the power drop to a capability change.
6329 // Once in dark wake, transition to sleep state ASAP.
6330
6331 darkWakeToSleepASAP = true;
6332
6333 // Drop graphics and audio capability
6334 _desiredCapability &= ~(
6335 kIOPMSystemCapabilityGraphics |
6336 kIOPMSystemCapabilityAudio);
6337
6338 // Convert to capability change (ON->ON)
6339 *inOutPowerState = getRUN_STATE();
6340 *inOutChangeFlags |= kIOPMSynchronize;
6341
6342 // Revert device desire from SLEEP to ON
6343 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6344 } else {
6345 // System is already in dark wake, ok to drop power state.
6346 // Broadcast root power down to entire tree.
6347 *inOutChangeFlags |= kIOPMRootChangeDown;
6348 }
6349 } else if (desiredPowerState > currentPowerState) {
6350 if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
6351 // Broadcast power up when waking from sleep, but not for the
6352 // initial power change at boot by checking for cpu capability.
6353 *inOutChangeFlags |= kIOPMRootChangeUp;
6354 }
6355 }
6356 }
6357
6358 void
6359 IOPMrootDomain::handleOurPowerChangeStart(
6360 IOService * service,
6361 IOPMActions * actions,
6362 const IOPMRequest * request,
6363 IOPMPowerStateIndex newPowerState,
6364 IOPMPowerChangeFlags * inOutChangeFlags )
6365 {
6366 IOPMRequestTag requestTag = request->getTag();
6367 IOPMRequestTag sleepReason;
6368
6369 uint32_t changeFlags = *inOutChangeFlags;
6370 uint32_t currentPowerState = (uint32_t) getPowerState();
6371 bool publishSleepReason = false;
6372
6373 // Check if request has a valid sleep reason
6374 sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6375 if (sleepReason < kIOPMSleepReasonClamshell) {
6376 sleepReason = kIOPMSleepReasonIdle;
6377 }
6378
6379 _systemTransitionType = kSystemTransitionNone;
6380 _systemMessageClientMask = 0;
6381 capabilityLoss = false;
6382 toldPowerdCapWillChange = false;
6383
6384 // Emergency notifications may arrive after the initial sleep request
6385 // has been queued. Override the sleep reason so powerd and others can
6386 // treat this as an emergency sleep.
6387 if (lowBatteryCondition) {
6388 sleepReason = kIOPMSleepReasonLowPower;
6389 } else if (thermalEmergencyState) {
6390 sleepReason = kIOPMSleepReasonThermalEmergency;
6391 }
6392
6393 // 1. Explicit capability change.
6394 if (changeFlags & kIOPMSynchronize) {
6395 if (newPowerState == ON_STATE) {
6396 if (changeFlags & kIOPMSyncNoChildNotify) {
6397 setSystemTransitionTypeGated(kSystemTransitionNewCapClient);
6398 } else {
6399 setSystemTransitionTypeGated(kSystemTransitionCapability);
6400 }
6401 }
6402 }
6403 // 2. Going to sleep (cancellation still possible).
6404 else if (newPowerState < currentPowerState) {
6405 setSystemTransitionTypeGated(kSystemTransitionSleep);
6406 }
6407 // 3. Woke from (idle or demand) sleep.
6408 else if (!systemBooting &&
6409 (changeFlags & kIOPMSelfInitiated) &&
6410 (newPowerState > currentPowerState)) {
6411 setSystemTransitionTypeGated(kSystemTransitionWake);
6412
6413 _desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
6414
6415 // Early exit from dark wake to full (e.g. LID open)
6416 if (kFullWakeReasonNone != fullWakeReason) {
6417 _desiredCapability |= (
6418 kIOPMSystemCapabilityGraphics |
6419 kIOPMSystemCapabilityAudio);
6420
6421 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6422 if (fullWakeReason == kFullWakeReasonLocalUser) {
6423 darkWakeExit = true;
6424 darkWakeToSleepASAP = false;
6425 setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ?
6426 kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser);
6427 }
6428 #endif
6429 }
6430 #if HIBERNATION
6431 IOHibernateSetWakeCapabilities(_desiredCapability);
6432 #endif
6433 }
6434
6435 // Update pending wake capability at the beginning of every
6436 // state transition (including synchronize). This will become
6437 // the current capability at the end of the transition.
6438
6439 if (kSystemTransitionSleep == _systemTransitionType) {
6440 _pendingCapability = 0;
6441 capabilityLoss = true;
6442 } else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6443 _pendingCapability = _desiredCapability |
6444 kIOPMSystemCapabilityCPU |
6445 kIOPMSystemCapabilityNetwork;
6446
6447 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6448 _pendingCapability |= kIOPMSystemCapabilityAudio;
6449 }
6450
6451 if ((kSystemTransitionCapability == _systemTransitionType) &&
6452 (_pendingCapability == _currentCapability)) {
6453 // Cancel the PM state change.
6454 setSystemTransitionTypeGated(kSystemTransitionNone);
6455 *inOutChangeFlags |= kIOPMNotDone;
6456 }
6457 if (__builtin_popcount(_pendingCapability) <
6458 __builtin_popcount(_currentCapability)) {
6459 capabilityLoss = true;
6460 }
6461 }
6462
6463 // 1. Capability change.
6464 if (kSystemTransitionCapability == _systemTransitionType) {
6465 // Dark to Full transition.
6466 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6467 tracePoint( kIOPMTracePointDarkWakeExit );
6468
6469 #if defined(XNU_TARGET_OS_OSX)
6470 // rdar://problem/65627936
6471 // When a dark->full wake promotion is scheduled before an ON->SLEEP
6472 // power state drop, invalidate any request to drop power state already
6473 // in the queue, including the override variant, unless full wake cannot
6474 // be sustained. Any power state drop queued after this SustainFullWake
6475 // request will not be affected.
6476 if (checkSystemCanSustainFullWake()) {
6477 changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake);
6478 }
6479 #endif
6480
6481 willEnterFullWake();
6482 }
6483
6484 // Full to Dark transition.
6485 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6486 // Clear previous stats
6487 IOLockLock(pmStatsLock);
6488 if (pmStatsAppResponses) {
6489 pmStatsAppResponses = OSArray::withCapacity(5);
6490 }
6491 IOLockUnlock(pmStatsLock);
6492
6493 tracePoint( kIOPMTracePointDarkWakeEntry );
6494 *inOutChangeFlags |= kIOPMSyncTellPowerDown;
6495 _systemMessageClientMask = kSystemMessageClientPowerd |
6496 kSystemMessageClientLegacyApp;
6497
6498 // rdar://15971327
6499 // Prevent user active transitions before notifying clients
6500 // that system will sleep.
6501 preventTransitionToUserActive(true);
6502
6503 IOService::setAdvisoryTickleEnable( false );
6504
6505 // Publish the sleep reason for full to dark wake
6506 publishSleepReason = true;
6507 lastSleepReason = fullToDarkReason = sleepReason;
6508
6509 // Publish a UUID for the Sleep --> Wake cycle
6510 handlePublishSleepWakeUUID(true);
6511 if (sleepDelaysReport) {
6512 clock_get_uptime(&ts_sleepStart);
6513 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
6514 }
6515
6516 darkWakeExit = false;
6517 }
6518 }
6519 // 2. System sleep.
6520 else if (kSystemTransitionSleep == _systemTransitionType) {
6521 // Beginning of a system sleep transition.
6522 // Cancellation is still possible.
6523 tracePoint( kIOPMTracePointSleepStarted );
6524
6525 _systemMessageClientMask = kSystemMessageClientAll;
6526 if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6527 _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6528 }
6529 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
6530 // Kernel priority clients are only notified on the initial
6531 // transition to full wake, so don't notify them unless system
6532 // has gained graphics capability since the last system wake.
6533 _systemMessageClientMask &= ~kSystemMessageClientKernel;
6534 } else {
6535 // System was in full wake, but the downwards power transition is driven
6536 // by a request that originates from IOServicePM, so it isn't tagged with
6537 // a valid system sleep reason.
6538 if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) {
6539 // Publish the same reason for full to dark
6540 sleepReason = fullToDarkReason;
6541 }
6542 }
6543 #if HIBERNATION
6544 gIOHibernateState = 0;
6545 #endif
6546
6547 // Record the reason for dark wake back to sleep
6548 // System may not have ever achieved full wake
6549
6550 publishSleepReason = true;
6551 lastSleepReason = sleepReason;
6552 if (sleepDelaysReport) {
6553 clock_get_uptime(&ts_sleepStart);
6554 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
6555 }
6556 }
6557 // 3. System wake.
6558 else if (kSystemTransitionWake == _systemTransitionType) {
6559 tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6560 // Clear stats about sleep
6561
6562 if (AOT_STATE == newPowerState) {
6563 _pendingCapability = kIOPMSystemCapabilityAOT;
6564 }
6565
6566 if (AOT_STATE == currentPowerState) {
6567 // Wake events are no longer accepted after waking to AOT_STATE.
6568 // Re-enable wake event acceptance to append wake events claimed
6569 // during the AOT to ON_STATE transition.
6570 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable);
6571 }
6572
6573 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6574 willEnterFullWake();
6575 }
6576 }
6577
6578 // The only location where the sleep reason is published. At this point
6579 // sleep can still be cancelled, but sleep reason should be published
6580 // early for logging purposes.
6581
6582 if (publishSleepReason) {
6583 static const char * IOPMSleepReasons[] =
6584 {
6585 kIOPMClamshellSleepKey,
6586 kIOPMPowerButtonSleepKey,
6587 kIOPMSoftwareSleepKey,
6588 kIOPMOSSwitchHibernationKey,
6589 kIOPMIdleSleepKey,
6590 kIOPMLowPowerSleepKey,
6591 kIOPMThermalEmergencySleepKey,
6592 kIOPMMaintenanceSleepKey,
6593 kIOPMSleepServiceExitKey,
6594 kIOPMDarkWakeThermalEmergencyKey,
6595 kIOPMNotificationWakeExitKey
6596 };
6597
6598 // Record sleep cause in IORegistry
6599 uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
6600 if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
6601 DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
6602 #if DEVELOPMENT || DEBUG
6603 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6604 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6605 "Sleep Reason", "%s\n", IOPMSleepReasons[reasonIndex]
6606 );
6607 #endif /* DEVELOPMENT || DEBUG */
6608 setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
6609 }
6610 }
6611
6612 if ((kSystemTransitionNone != _systemTransitionType) &&
6613 (kSystemTransitionNewCapClient != _systemTransitionType)) {
6614 _systemStateGeneration++;
6615 systemDarkWake = false;
6616
6617 DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6618 getPowerStateString(currentPowerState),
6619 getPowerStateString((uint32_t) newPowerState),
6620 _currentCapability, _pendingCapability,
6621 *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask,
6622 requestTag);
6623 #if DEVELOPMENT || DEBUG
6624 if (currentPowerState != (uint32_t) newPowerState) {
6625 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6626 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6627 "Start Power State Trans.",
6628 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6629 getPowerStateString(currentPowerState),
6630 getPowerStateString((uint32_t) newPowerState),
6631 _currentCapability,
6632 _pendingCapability,
6633 *inOutChangeFlags,
6634 _systemStateGeneration,
6635 _systemMessageClientMask,
6636 requestTag
6637 );
6638 }
6639 #endif /* DEVELOPMENT || DEBUG */
6640 }
6641
6642 if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6643 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6644 }
6645 if (_aotNow && (ON_STATE == newPowerState)) {
6646 WAKEEVENT_LOCK();
6647 aotShouldExit(true);
6648 WAKEEVENT_UNLOCK();
6649 aotExit(false);
6650 }
6651 }
6652
6653 void
6654 IOPMrootDomain::setSystemTransitionTypeGated(SystemTransitionType type)
6655 {
6656 assert(gIOPMWorkLoop->inGate());
6657 _systemTransitionType = type;
6658 commandGate->commandWakeup(&_systemTransitionType);
6659 }
6660
6661 void
6662 IOPMrootDomain::waitForSystemTransitionToMinPowerState(IOPMRootDomainPowerState state)
6663 {
6664 while (true) {
6665 IOReturn ret = gIOPMWorkLoop->runActionBlock(^{
6666 // Block until all in progress transitions have completed.
6667 while (_systemTransitionType != kSystemTransitionNone) {
6668 commandGate->commandSleep(&_systemTransitionType);
6669 }
6670
6671 // Check the current power state.
6672 if (getPowerState() >= state) {
6673 return kIOReturnSuccess;
6674 }
6675
6676 return kIOReturnError;
6677 });
6678
6679 if (ret == kIOReturnSuccess) {
6680 break;
6681 }
6682 }
6683 }
6684
6685 void
6686 IOPMrootDomain::handleOurPowerChangeDone(
6687 IOService * service,
6688 IOPMActions * actions,
6689 const IOPMRequest * request,
6690 IOPMPowerStateIndex oldPowerState,
6691 IOPMPowerChangeFlags changeFlags )
6692 {
6693 if (kSystemTransitionNewCapClient == _systemTransitionType) {
6694 setSystemTransitionTypeGated(kSystemTransitionNone);
6695 return;
6696 }
6697
6698 if (_systemTransitionType != kSystemTransitionNone) {
6699 uint32_t currentPowerState = (uint32_t) getPowerState();
6700
6701 if (changeFlags & kIOPMNotDone) {
6702 // Power down was cancelled or vetoed.
6703 _pendingCapability = _currentCapability;
6704 lastSleepReason = 0;
6705
6706 // When sleep is cancelled or reverted, don't report
6707 // the target (lower) power state as the previous state.
6708 oldPowerState = currentPowerState;
6709
6710 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
6711 CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
6712 #if defined(XNU_TARGET_OS_OSX)
6713 pmPowerStateQueue->submitPowerEvent(
6714 kPowerEventPolicyStimulus,
6715 (void *) kStimulusDarkWakeReentry,
6716 _systemStateGeneration );
6717 #else /* !defined(XNU_TARGET_OS_OSX) */
6718 // On embedded, there are no factors that can prolong a
6719 // "darkWake" when a power down is vetoed. We need to
6720 // promote to "fullWake" at least once so that factors
6721 // that prevent idle sleep can assert themselves if required
6722 pmPowerStateQueue->submitPowerEvent(
6723 kPowerEventPolicyStimulus,
6724 (void *) kStimulusDarkWakeActivityTickle);
6725 #endif /* !defined(XNU_TARGET_OS_OSX) */
6726 }
6727
6728 // Revert device desire to max.
6729 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6730 } else {
6731 // Send message on dark wake to full wake promotion.
6732 // tellChangeUp() handles the normal SLEEP->ON case.
6733
6734 if (kSystemTransitionCapability == _systemTransitionType) {
6735 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6736 lastSleepReason = 0; // stop logging wrangler tickles
6737 tellClients(kIOMessageSystemHasPoweredOn);
6738 }
6739 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6740 // Going dark, reset full wake state
6741 // userIsActive will be cleared by wrangler powering down
6742 fullWakeReason = kFullWakeReasonNone;
6743
6744 if (ts_sleepStart) {
6745 clock_get_uptime(&wake2DarkwakeDelay);
6746 SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
6747 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
6748 ts_sleepStart = 0;
6749 }
6750 }
6751 }
6752
6753 // Reset state after exiting from dark wake.
6754
6755 if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6756 CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6757 darkWakeMaintenance = false;
6758 darkWakeToSleepASAP = false;
6759 pciCantSleepValid = false;
6760 darkWakeSleepService = false;
6761
6762 if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6763 // Remove the influence of display power assertion
6764 // before next system wake.
6765 if (wrangler) {
6766 wrangler->changePowerStateForRootDomain(
6767 kWranglerPowerStateMin );
6768 }
6769 removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6770 }
6771 }
6772
6773 // Entered dark mode.
6774
6775 if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6776 (_pendingCapability & kIOPMSystemCapabilityCPU)) {
6777 // Queue an evaluation of whether to remain in dark wake,
6778 // and for how long. This serves the purpose of draining
6779 // any assertions from the queue.
6780
6781 pmPowerStateQueue->submitPowerEvent(
6782 kPowerEventPolicyStimulus,
6783 (void *) kStimulusDarkWakeEntry,
6784 _systemStateGeneration );
6785 }
6786 }
6787
6788 #if DEVELOPMENT || DEBUG
6789 if (currentPowerState != (uint32_t) oldPowerState) {
6790 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6791 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6792 "Finish Power State Trans.",
6793 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6794 getPowerStateString((uint32_t)oldPowerState),
6795 getPowerStateString(currentPowerState),
6796 _currentCapability,
6797 _pendingCapability,
6798 changeFlags,
6799 _systemStateGeneration,
6800 _systemMessageClientMask,
6801 request->getTag()
6802 );
6803 }
6804 #endif /* DEVELOPMENT || DEBUG */
6805
6806 DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6807 getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState),
6808 _currentCapability, _pendingCapability,
6809 changeFlags, _systemStateGeneration, _systemMessageClientMask,
6810 request->getTag());
6811
6812 if ((currentPowerState == ON_STATE) && pmAssertions) {
6813 pmAssertions->reportCPUBitAccounting();
6814 }
6815
6816 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6817 displayWakeCnt++;
6818 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6819 if (clamshellExists && fullWakeThreadCall) {
6820 AbsoluteTime deadline;
6821 clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline);
6822 thread_call_enter_delayed(fullWakeThreadCall, deadline);
6823 }
6824 #endif
6825 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6826 darkWakeCnt++;
6827 }
6828
6829 // Update current system capability.
6830 if (_currentCapability != _pendingCapability) {
6831 _currentCapability = _pendingCapability;
6832 }
6833
6834 // Update highest system capability.
6835
6836 _highestCapability |= _currentCapability;
6837
6838 if (darkWakePostTickle &&
6839 (kSystemTransitionWake == _systemTransitionType) &&
6840 (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6841 kDarkWakeFlagPromotionLate) {
6842 darkWakePostTickle = false;
6843 reportUserInput();
6844 } else if (darkWakeExit) {
6845 requestFullWake( kFullWakeReasonLocalUser );
6846 }
6847
6848 // Reset tracepoint at completion of capability change,
6849 // completion of wake transition, and aborted sleep transition.
6850
6851 if ((_systemTransitionType == kSystemTransitionCapability) ||
6852 (_systemTransitionType == kSystemTransitionWake) ||
6853 ((_systemTransitionType == kSystemTransitionSleep) &&
6854 (changeFlags & kIOPMNotDone))) {
6855 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6856 tracePoint( kIOPMTracePointSystemUp );
6857 }
6858
6859 setSystemTransitionTypeGated(kSystemTransitionNone);
6860
6861 _systemMessageClientMask = 0;
6862 toldPowerdCapWillChange = false;
6863
6864 darkWakeLogClamp = false;
6865
6866 if (lowBatteryCondition) {
6867 privateSleepSystem(kIOPMSleepReasonLowPower);
6868 } else if (thermalEmergencyState) {
6869 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6870 } else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) {
6871 // Request for full wake is removed while system is waking up to full wake
6872 DLOG("DisplayOn fullwake request is removed\n");
6873 handleSetDisplayPowerOn(false);
6874 }
6875
6876 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6877 pmPowerStateQueue->submitPowerEvent(
6878 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6879 }
6880 }
6881 }
6882
6883 //******************************************************************************
6884 // PM actions for graphics and audio.
6885 //******************************************************************************
6886
6887 void
6888 IOPMrootDomain::overridePowerChangeForService(
6889 IOService * service,
6890 IOPMActions * actions,
6891 const IOPMRequest * request,
6892 IOPMPowerStateIndex * inOutPowerState,
6893 IOPMPowerChangeFlags * inOutChangeFlags )
6894 {
6895 uint32_t powerState = (uint32_t) *inOutPowerState;
6896 uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6897 const uint32_t actionFlags = actions->flags;
6898
6899 if (kSystemTransitionNone == _systemTransitionType) {
6900 // Not in midst of a system transition.
6901 // Do not set kPMActionsStatePowerClamped.
6902 } else if ((actions->state & kPMActionsStatePowerClamped) == 0) {
6903 bool enableClamp = false;
6904
6905 // For most drivers, enable the clamp during ON->Dark transition
6906 // which has the kIOPMSynchronize flag set in changeFlags.
6907 if ((actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6908 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6909 (changeFlags & kIOPMSynchronize)) {
6910 enableClamp = true;
6911 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6912 ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6913 ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6914 (changeFlags & kIOPMSynchronize)) {
6915 enableClamp = true;
6916 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6917 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6918 (changeFlags & kIOPMSynchronize)) {
6919 enableClamp = true;
6920 } else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) &&
6921 (_systemTransitionType == kSystemTransitionSleep)) {
6922 // For graphics drivers, clamp power when entering
6923 // system sleep. Not when dropping to dark wake.
6924 enableClamp = true;
6925 }
6926
6927 if (enableClamp) {
6928 actions->state |= kPMActionsStatePowerClamped;
6929 DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6930 service->getName(), service->getRegistryEntryID(),
6931 _pendingCapability, powerState, changeFlags);
6932 }
6933 } else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6934 bool disableClamp = false;
6935
6936 if ((actionFlags & (
6937 kPMActionsFlagIsDisplayWrangler |
6938 kPMActionsFlagIsGraphicsDriver)) &&
6939 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6940 disableClamp = true;
6941 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6942 (_pendingCapability & kIOPMSystemCapabilityAudio)) {
6943 disableClamp = true;
6944 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6945 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6946 disableClamp = true;
6947 }
6948
6949 if (disableClamp) {
6950 actions->state &= ~kPMActionsStatePowerClamped;
6951 DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6952 service->getName(), service->getRegistryEntryID(),
6953 _pendingCapability, powerState, changeFlags);
6954 }
6955 }
6956
6957 if (actions->state & kPMActionsStatePowerClamped) {
6958 uint32_t maxPowerState = 0;
6959
6960 // Determine the max power state allowed when clamp is enabled
6961 if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
6962 // Parent intiated power state changes
6963 if ((service->getPowerState() > maxPowerState) &&
6964 (actionFlags & kPMActionsFlagIsDisplayWrangler)) {
6965 maxPowerState++;
6966
6967 // Remove lingering effects of any tickle before entering
6968 // dark wake. It will take a new tickle to return to full
6969 // wake, so the existing tickle state is useless.
6970
6971 if (changeFlags & kIOPMDomainDidChange) {
6972 *inOutChangeFlags |= kIOPMExpireIdleTimer;
6973 }
6974 } else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6975 maxPowerState++;
6976 } else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6977 maxPowerState = actions->darkWakePowerState;
6978 }
6979 } else {
6980 // Deny all self-initiated changes when power is limited.
6981 // Wrangler tickle should never defeat the limiter.
6982 maxPowerState = service->getPowerState();
6983 }
6984
6985 if (powerState > maxPowerState) {
6986 DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6987 service->getName(), service->getRegistryEntryID(),
6988 powerState, maxPowerState, changeFlags);
6989 *inOutPowerState = maxPowerState;
6990
6991 if (darkWakePostTickle &&
6992 (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6993 (changeFlags & kIOPMDomainWillChange) &&
6994 ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6995 kDarkWakeFlagPromotionEarly)) {
6996 darkWakePostTickle = false;
6997 reportUserInput();
6998 }
6999 }
7000
7001 if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
7002 if (darkWakeLogClamp) {
7003 AbsoluteTime now;
7004 uint64_t nsec;
7005
7006 clock_get_uptime(&now);
7007 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
7008 absolutetime_to_nanoseconds(now, &nsec);
7009 DLOG("dark wake power clamped after %u ms\n",
7010 ((int)((nsec) / NSEC_PER_MSEC)));
7011 }
7012 darkWakePowerClamped = true;
7013 }
7014 }
7015 }
7016
7017 void
7018 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
7019 IOService * service,
7020 IOPMActions * actions )
7021 {
7022 #if DISPLAY_WRANGLER_PRESENT
7023 // Warning: Not running in PM work loop context - don't modify state !!!
7024 // Trap tickle directed to IODisplayWrangler while running with graphics
7025 // capability suppressed.
7026
7027 assert(service == wrangler);
7028
7029 clock_get_uptime(&userActivityTime);
7030 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
7031 || (lastSleepReason == kIOPMSleepReasonMaintenance)
7032 || (lastSleepReason == kIOPMSleepReasonSoftware));
7033 if (aborting) {
7034 userActivityCount++;
7035 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
7036 userActivityCount, lastSleepReason);
7037 }
7038
7039 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7040 DLOG("display wrangler tickled\n");
7041 if (kIOLogPMRootDomain & gIOKitDebug) {
7042 OSReportWithBacktrace("Dark wake display tickle");
7043 }
7044 if (pmPowerStateQueue) {
7045 pmPowerStateQueue->submitPowerEvent(
7046 kPowerEventPolicyStimulus,
7047 (void *) kStimulusDarkWakeActivityTickle,
7048 true /* set wake type */ );
7049 }
7050 }
7051 #endif /* DISPLAY_WRANGLER_PRESENT */
7052 }
7053
7054 void
7055 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
7056 IOService * service,
7057 IOPMActions * actions,
7058 const OSSymbol * powerClient,
7059 IOPMPowerStateIndex oldPowerState,
7060 IOPMPowerStateIndex newPowerState )
7061 {
7062 #if DISPLAY_WRANGLER_PRESENT
7063 assert(service == wrangler);
7064
7065 // This function implements half of the user active detection
7066 // by monitoring changes to the display wrangler's device desire.
7067 //
7068 // User becomes active when either:
7069 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
7070 // in max power state. This desire change in absence of a power state
7071 // change is detected within. This handles the case when user becomes
7072 // active while the display is already lit by setDisplayPowerOn().
7073 //
7074 // 2. Power state change to max, and DeviceDesire is also at max.
7075 // Handled by displayWranglerNotification().
7076 //
7077 // User becomes inactive when DeviceDesire drops to sleep state or below.
7078
7079 DLOG("wrangler %s (ps %u, %u->%u)\n",
7080 powerClient->getCStringNoCopy(),
7081 (uint32_t) service->getPowerState(),
7082 (uint32_t) oldPowerState, (uint32_t) newPowerState);
7083
7084 if (powerClient == gIOPMPowerClientDevice) {
7085 if ((newPowerState > oldPowerState) &&
7086 (newPowerState == kWranglerPowerStateMax) &&
7087 (service->getPowerState() == kWranglerPowerStateMax)) {
7088 evaluatePolicy( kStimulusEnterUserActiveState );
7089 } else if ((newPowerState < oldPowerState) &&
7090 (newPowerState <= kWranglerPowerStateSleep)) {
7091 evaluatePolicy( kStimulusLeaveUserActiveState );
7092 }
7093 }
7094
7095 if (newPowerState <= kWranglerPowerStateSleep) {
7096 evaluatePolicy( kStimulusDisplayWranglerSleep );
7097 } else if (newPowerState == kWranglerPowerStateMax) {
7098 evaluatePolicy( kStimulusDisplayWranglerWake );
7099 }
7100 #endif /* DISPLAY_WRANGLER_PRESENT */
7101 }
7102
7103 //******************************************************************************
7104 // User active state management
7105 //******************************************************************************
7106
7107 void
7108 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
7109 {
7110 #if DISPLAY_WRANGLER_PRESENT
7111 _preventUserActive = prevent;
7112 if (wrangler && !_preventUserActive) {
7113 // Allowing transition to user active, but the wrangler may have
7114 // already powered ON in case of sleep cancel/revert. Poll the
7115 // same conditions checked for in displayWranglerNotification()
7116 // to bring the user active state up to date.
7117
7118 if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
7119 (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
7120 kWranglerPowerStateMax)) {
7121 evaluatePolicy( kStimulusEnterUserActiveState );
7122 }
7123 }
7124 #endif /* DISPLAY_WRANGLER_PRESENT */
7125 }
7126
7127 //******************************************************************************
7128 // Approve usage of delayed child notification by PM.
7129 //******************************************************************************
7130
7131 bool
7132 IOPMrootDomain::shouldDelayChildNotification(
7133 IOService * service )
7134 {
7135 if ((kFullWakeReasonNone == fullWakeReason) &&
7136 (kSystemTransitionWake == _systemTransitionType)) {
7137 DLOG("%s: delay child notify\n", service->getName());
7138 return true;
7139 }
7140 return false;
7141 }
7142
7143 //******************************************************************************
7144 // PM actions for PCI device.
7145 //******************************************************************************
7146
7147 void
7148 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
7149 IOService * service,
7150 IOPMActions * actions,
7151 const IOPMRequest * request,
7152 IOPMPowerStateIndex powerState,
7153 IOPMPowerChangeFlags * inOutChangeFlags )
7154 {
7155 pmTracer->tracePCIPowerChange(
7156 PMTraceWorker::kPowerChangeStart,
7157 service, *inOutChangeFlags,
7158 (actions->flags & kPMActionsPCIBitNumberMask));
7159 }
7160
7161 void
7162 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
7163 IOService * service,
7164 IOPMActions * actions,
7165 const IOPMRequest * request,
7166 IOPMPowerStateIndex powerState,
7167 IOPMPowerChangeFlags changeFlags )
7168 {
7169 pmTracer->tracePCIPowerChange(
7170 PMTraceWorker::kPowerChangeCompleted,
7171 service, changeFlags,
7172 (actions->flags & kPMActionsPCIBitNumberMask));
7173 }
7174
7175 //******************************************************************************
7176 // registerInterest
7177 //
7178 // Override IOService::registerInterest() for root domain clients.
7179 //******************************************************************************
7180
7181 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
7182 {
7183 friend class IOPMrootDomain;
7184 OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
7185
7186 protected:
7187 uint32_t ackTimeoutCnt;
7188 uint32_t msgType; // Last type seen by the message filter
7189 uint32_t lastSleepWakeMsgType;
7190 uint32_t msgIndex;
7191 uint32_t maxMsgDelayMS;
7192 uint32_t maxAckDelayMS;
7193 uint64_t msgAbsTime;
7194 uint64_t uuid0;
7195 uint64_t uuid1;
7196 OSSharedPtr<const OSSymbol> identifier;
7197 OSSharedPtr<const OSSymbol> clientName;
7198 };
7199
7200 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
7201
7202 OSSharedPtr<IONotifier>
7203 IOPMrootDomain::registerInterest(
7204 const OSSymbol * typeOfInterest,
7205 IOServiceInterestHandler handler,
7206 void * target, void * ref )
7207 {
7208 IOPMServiceInterestNotifier* notifier;
7209 bool isSystemCapabilityClient;
7210 bool isKernelCapabilityClient;
7211 IOReturn rc = kIOReturnError;
7212
7213 isSystemCapabilityClient = typeOfInterest &&
7214 typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
7215
7216 isKernelCapabilityClient = typeOfInterest &&
7217 typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
7218
7219 if (isSystemCapabilityClient) {
7220 typeOfInterest = gIOAppPowerStateInterest;
7221 }
7222
7223 notifier = new IOPMServiceInterestNotifier;
7224 if (!notifier) {
7225 return NULL;
7226 }
7227
7228 if (notifier->init()) {
7229 rc = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
7230 }
7231 if (rc != kIOReturnSuccess) {
7232 OSSafeReleaseNULL(notifier);
7233 return NULL;
7234 }
7235
7236 notifier->ackTimeoutCnt = 0;
7237
7238 if (pmPowerStateQueue) {
7239 if (isSystemCapabilityClient) {
7240 notifier->retain();
7241 if (pmPowerStateQueue->submitPowerEvent(
7242 kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
7243 notifier->release();
7244 }
7245 }
7246
7247 if (isKernelCapabilityClient) {
7248 notifier->retain();
7249 if (pmPowerStateQueue->submitPowerEvent(
7250 kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
7251 notifier->release();
7252 }
7253 }
7254 }
7255
7256 OSSharedPtr<OSData> data;
7257 uint8_t *uuid = NULL;
7258 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
7259 if (kext) {
7260 data = kext->copyUUID();
7261 }
7262 if (data && (data->getLength() == sizeof(uuid_t))) {
7263 uuid = (uint8_t *)(data->getBytesNoCopy());
7264
7265 notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
7266 ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
7267 ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
7268 notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
7269 ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
7270 ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
7271
7272 notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
7273 }
7274 return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
7275 }
7276
7277 //******************************************************************************
7278 // systemMessageFilter
7279 //
7280 //******************************************************************************
7281
7282 bool
7283 IOPMrootDomain::systemMessageFilter(
7284 void * object, void * arg1, void * arg2, void * arg3 )
7285 {
7286 const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
7287 bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
7288 bool isCapPowerd = (object == (void *) systemCapabilityNotifier.get());
7289 bool isCapClient = false;
7290 bool allow = false;
7291 OSBoolean **waitForReply = (typeof(waitForReply))arg3;
7292 IOPMServiceInterestNotifier *notifier;
7293
7294 notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
7295
7296 do {
7297 // When powerd and kernel priority clients register capability interest,
7298 // the power tree is sync'ed to inform those clients about the current
7299 // system capability. Only allow capability change messages during sync.
7300 if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
7301 (!isCapMsg || !_joinedCapabilityClients ||
7302 !_joinedCapabilityClients->containsObject((OSObject *) object))) {
7303 break;
7304 }
7305
7306 // Capability change message for powerd and kernel clients
7307 if (isCapMsg) {
7308 // Kernel priority clients
7309 if ((context->notifyType == kNotifyPriority) ||
7310 (context->notifyType == kNotifyCapabilityChangePriority)) {
7311 isCapClient = true;
7312 }
7313
7314 // powerd will maintain two client registrations with root domain.
7315 // isCapPowerd will be TRUE for any message targeting the powerd
7316 // exclusive (capability change) interest registration.
7317 if (isCapPowerd && (context->notifyType == kNotifyCapabilityChangeApps)) {
7318 isCapClient = true;
7319 }
7320 }
7321
7322 if (isCapClient) {
7323 IOPMSystemCapabilityChangeParameters * capArgs =
7324 (IOPMSystemCapabilityChangeParameters *) arg2;
7325
7326 if (kSystemTransitionNewCapClient == _systemTransitionType) {
7327 capArgs->fromCapabilities = 0;
7328 capArgs->toCapabilities = _currentCapability;
7329 capArgs->changeFlags = 0;
7330 } else {
7331 capArgs->fromCapabilities = _currentCapability;
7332 capArgs->toCapabilities = _pendingCapability;
7333
7334 if (context->isPreChange) {
7335 capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
7336 } else {
7337 capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
7338 }
7339
7340 if (isCapPowerd && context->isPreChange) {
7341 toldPowerdCapWillChange = true;
7342 }
7343 }
7344
7345 // App level capability change messages must only go to powerd.
7346 // Wait for response post-change if capabilitiy is increasing.
7347 // Wait for response pre-change if capability is decreasing.
7348
7349 if ((context->notifyType == kNotifyCapabilityChangeApps) && waitForReply &&
7350 ((capabilityLoss && context->isPreChange) ||
7351 (!capabilityLoss && !context->isPreChange))) {
7352 *waitForReply = kOSBooleanTrue;
7353 }
7354
7355 allow = true;
7356 break;
7357 }
7358
7359 // powerd will always receive CanSystemSleep, even for a demand sleep.
7360 // It will also have a final chance to veto sleep after all clients
7361 // have responded to SystemWillSleep
7362
7363 if ((kIOMessageCanSystemSleep == context->messageType) ||
7364 (kIOMessageSystemWillNotSleep == context->messageType)) {
7365 if (isCapPowerd) {
7366 allow = true;
7367 break;
7368 }
7369
7370 // Demand sleep, don't ask apps for permission
7371 if (context->changeFlags & kIOPMSkipAskPowerDown) {
7372 break;
7373 }
7374 }
7375
7376 if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
7377 if (isCapPowerd && CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
7378 (fullToDarkReason == kIOPMSleepReasonIdle)) {
7379 allow = true;
7380 }
7381 break;
7382 }
7383
7384 // Drop capability change messages for legacy clients.
7385 // Drop legacy system sleep messages for powerd capability interest.
7386 if (isCapMsg || isCapPowerd) {
7387 break;
7388 }
7389
7390 // Not a capability change message.
7391 // Perform message filtering based on _systemMessageClientMask.
7392
7393 if ((context->notifyType == kNotifyApps) &&
7394 (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7395 if (!notifier) {
7396 break;
7397 }
7398
7399 if ((notifier->lastSleepWakeMsgType == context->messageType) &&
7400 (notifier->lastSleepWakeMsgType == kIOMessageSystemWillPowerOn)) {
7401 break; // drop any duplicate WillPowerOn for AOT devices
7402 }
7403
7404 allow = true;
7405
7406 if (waitForReply) {
7407 if (notifier->ackTimeoutCnt >= 3) {
7408 *waitForReply = kOSBooleanFalse;
7409 } else {
7410 *waitForReply = kOSBooleanTrue;
7411 }
7412 }
7413 } else if ((context->notifyType == kNotifyPriority) &&
7414 (_systemMessageClientMask & kSystemMessageClientKernel)) {
7415 allow = true;
7416 }
7417
7418 // Check sleep/wake message ordering
7419 if (allow) {
7420 if (context->messageType == kIOMessageSystemWillSleep ||
7421 context->messageType == kIOMessageSystemWillPowerOn ||
7422 context->messageType == kIOMessageSystemHasPoweredOn) {
7423 notifier->lastSleepWakeMsgType = context->messageType;
7424 }
7425 }
7426 } while (false);
7427
7428 if (allow && isCapMsg && _joinedCapabilityClients) {
7429 _joinedCapabilityClients->removeObject((OSObject *) object);
7430 if (_joinedCapabilityClients->getCount() == 0) {
7431 DMSG("destroyed capability client set %p\n",
7432 OBFUSCATE(_joinedCapabilityClients.get()));
7433 _joinedCapabilityClients.reset();
7434 }
7435 }
7436 if (notifier) {
7437 // Record the last seen message type even if the message is dropped
7438 // for traceFilteredNotification().
7439 notifier->msgType = context->messageType;
7440 }
7441
7442 return allow;
7443 }
7444
7445 //******************************************************************************
7446 // setMaintenanceWakeCalendar
7447 //
7448 //******************************************************************************
7449
7450 IOReturn
7451 IOPMrootDomain::setMaintenanceWakeCalendar(
7452 const IOPMCalendarStruct * calendar )
7453 {
7454 OSSharedPtr<OSData> data;
7455 IOReturn ret = 0;
7456
7457 if (!calendar) {
7458 return kIOReturnBadArgument;
7459 }
7460
7461 data = OSData::withValue(*calendar);
7462 if (!data) {
7463 return kIOReturnNoMemory;
7464 }
7465
7466 if (kPMCalendarTypeMaintenance == calendar->selector) {
7467 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get());
7468 } else if (kPMCalendarTypeSleepService == calendar->selector) {
7469 ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get());
7470 }
7471
7472 return ret;
7473 }
7474
7475 // MARK: -
7476 // MARK: Display Wrangler
7477
7478 //******************************************************************************
7479 // displayWranglerNotification
7480 //
7481 // Handle the notification when the IODisplayWrangler changes power state.
7482 //******************************************************************************
7483
7484 IOReturn
7485 IOPMrootDomain::displayWranglerNotification(
7486 void * target, void * refCon,
7487 UInt32 messageType, IOService * service,
7488 void * messageArgument, vm_size_t argSize )
7489 {
7490 #if DISPLAY_WRANGLER_PRESENT
7491 IOPMPowerStateIndex displayPowerState;
7492 IOPowerStateChangeNotification * params =
7493 (IOPowerStateChangeNotification *) messageArgument;
7494
7495 if ((messageType != kIOMessageDeviceWillPowerOff) &&
7496 (messageType != kIOMessageDeviceHasPoweredOn)) {
7497 return kIOReturnUnsupported;
7498 }
7499
7500 ASSERT_GATED();
7501 if (!gRootDomain) {
7502 return kIOReturnUnsupported;
7503 }
7504
7505 displayPowerState = params->stateNumber;
7506 DLOG("wrangler %s ps %d\n",
7507 getIOMessageString(messageType), (uint32_t) displayPowerState);
7508
7509 switch (messageType) {
7510 case kIOMessageDeviceWillPowerOff:
7511 // Display wrangler has dropped power due to display idle
7512 // or force system sleep.
7513 //
7514 // 4 Display ON kWranglerPowerStateMax
7515 // 3 Display Dim kWranglerPowerStateDim
7516 // 2 Display Sleep kWranglerPowerStateSleep
7517 // 1 Not visible to user
7518 // 0 Not visible to user kWranglerPowerStateMin
7519
7520 if (displayPowerState <= kWranglerPowerStateSleep) {
7521 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7522 }
7523 break;
7524
7525 case kIOMessageDeviceHasPoweredOn:
7526 // Display wrangler has powered on due to user activity
7527 // or wake from sleep.
7528
7529 if (kWranglerPowerStateMax == displayPowerState) {
7530 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7531
7532 // See comment in handleUpdatePowerClientForDisplayWrangler
7533 if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7534 kWranglerPowerStateMax) {
7535 gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7536 }
7537 }
7538 break;
7539 }
7540 #endif /* DISPLAY_WRANGLER_PRESENT */
7541 return kIOReturnUnsupported;
7542 }
7543
7544 //******************************************************************************
7545 // reportUserInput
7546 //
7547 //******************************************************************************
7548
7549 void
7550 IOPMrootDomain::updateUserActivity( void )
7551 {
7552 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7553 clock_get_uptime(&userActivityTime);
7554 bool aborting = ((lastSleepReason == kIOPMSleepReasonSoftware)
7555 || (lastSleepReason == kIOPMSleepReasonIdle)
7556 || (lastSleepReason == kIOPMSleepReasonMaintenance));
7557 if (aborting) {
7558 userActivityCount++;
7559 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7560 }
7561 #endif
7562 }
7563 void
7564 IOPMrootDomain::reportUserInput( void )
7565 {
7566 if (wrangler) {
7567 wrangler->activityTickle(0, 0);
7568 }
7569 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7570 // Update user activity
7571 updateUserActivity();
7572
7573 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7574 // update user active abs time
7575 clock_get_uptime(&gUserActiveAbsTime);
7576 pmPowerStateQueue->submitPowerEvent(
7577 kPowerEventPolicyStimulus,
7578 (void *) kStimulusDarkWakeActivityTickle,
7579 true /* set wake type */ );
7580 }
7581 #endif
7582 }
7583
7584 void
7585 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7586 {
7587 #if DISPLAY_WRANGLER_PRESENT
7588 if (wrangler) {
7589 wrangler->activityTickle(0, 0);
7590 }
7591 #else
7592 if (!device) {
7593 DLOG("requestUserActive: device is null\n");
7594 return;
7595 }
7596 OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7597 uint64_t registryID = device->getRegistryEntryID();
7598
7599 if (!deviceName || !registryID) {
7600 DLOG("requestUserActive: no device name or registry entry\n");
7601 return;
7602 }
7603 const char *name = deviceName->getCStringNoCopy();
7604 char payload[128];
7605 snprintf(payload, sizeof(payload), "%s:%s", name, reason);
7606 DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason);
7607 messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload));
7608 #endif
7609 }
7610
7611 //******************************************************************************
7612 // latchDisplayWranglerTickle
7613 //******************************************************************************
7614
7615 bool
7616 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7617 {
7618 #if DISPLAY_WRANGLER_PRESENT
7619 if (latch) {
7620 if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
7621 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7622 !checkSystemCanSustainFullWake()) {
7623 // Currently in dark wake, and not transitioning to full wake.
7624 // Full wake is unsustainable, so latch the tickle to prevent
7625 // the display from lighting up momentarily.
7626 wranglerTickled = true;
7627 } else {
7628 wranglerTickled = false;
7629 }
7630 } else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7631 wranglerTickled = false;
7632
7633 pmPowerStateQueue->submitPowerEvent(
7634 kPowerEventPolicyStimulus,
7635 (void *) kStimulusDarkWakeActivityTickle );
7636 }
7637
7638 return wranglerTickled;
7639 #else /* ! DISPLAY_WRANGLER_PRESENT */
7640 return false;
7641 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7642 }
7643
7644 //******************************************************************************
7645 // setDisplayPowerOn
7646 //
7647 // For root domain user client
7648 //******************************************************************************
7649
7650 void
7651 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7652 {
7653 pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7654 (void *) NULL, options );
7655 }
7656
7657 // MARK: -
7658 // MARK: System PM Policy
7659
7660 //******************************************************************************
7661 // checkSystemSleepAllowed
7662 //
7663 //******************************************************************************
7664
7665 bool
7666 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7667 uint32_t sleepReason )
7668 {
7669 uint32_t err = 0;
7670
7671 // Conditions that prevent idle and demand system sleep.
7672
7673 do {
7674 if (gSleepDisabledFlag) {
7675 err = kPMConfigPreventSystemSleep;
7676 break;
7677 }
7678
7679 if (userDisabledAllSleep) {
7680 err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7681 break;
7682 }
7683
7684 if (systemBooting || systemShutdown || gWillShutdown) {
7685 err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7686 break;
7687 }
7688
7689 if (options == 0) {
7690 break;
7691 }
7692
7693 // Conditions above pegs the system at full wake.
7694 // Conditions below prevent system sleep but does not prevent
7695 // dark wake, and must be called from gated context.
7696
7697 #if !CONFIG_SLEEP
7698 err = kPMConfigPreventSystemSleep; // 3. config does not support sleep
7699 break;
7700 #endif
7701
7702 if (_driverKitMatchingAssertionCount != 0 || _driverKitSyncedAssertionCount != 0) {
7703 err = kPMCPUAssertion;
7704 break;
7705 }
7706
7707 // Check for any dexts currently being added to the PM tree. Sleeping while
7708 // this is in flight can cause IOServicePH to timeout.
7709 if (!IOServicePH::checkPMReady()) {
7710 #if !defined(XNU_TARGET_OS_OSX)
7711 if (!(lowBatteryCondition || thermalWarningState || thermalEmergencyState)) {
7712 // 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
7713 // in dark wake for long periods of time, which causes issues as apps were
7714 // already informed of sleep during the f->9 transition. As a temporary
7715 // measure, always full wake if we hit this specific condition.
7716 pmPowerStateQueue->submitPowerEvent(
7717 kPowerEventPolicyStimulus,
7718 (void *) kStimulusDarkWakeActivityTickle);
7719 }
7720 #endif
7721 err = kPMDKNotReady;
7722 break;
7723 }
7724
7725 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7726 break; // always sleep on low battery or when in thermal warning/emergency state
7727 }
7728
7729 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7730 break; // always sleep on dark wake thermal emergencies
7731 }
7732
7733 if (preventSystemSleepList->getCount() != 0) {
7734 err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7735 break;
7736 }
7737
7738
7739 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7740 kIOPMDriverAssertionLevelOn) {
7741 err = kPMCPUAssertion; // 5. CPU assertion
7742 break;
7743 }
7744
7745 if (pciCantSleepValid) {
7746 if (pciCantSleepFlag) {
7747 err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7748 }
7749 break;
7750 } else if (sleepSupportedPEFunction &&
7751 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7752 IOReturn ret;
7753 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7754 ret = getPlatform()->callPlatformFunction(
7755 sleepSupportedPEFunction.get(), false,
7756 NULL, NULL, NULL, NULL);
7757 pciCantSleepValid = true;
7758 pciCantSleepFlag = false;
7759 if ((platformSleepSupport & kPCICantSleep) ||
7760 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7761 err = 6; // 6. PCI card does not support PM
7762 pciCantSleepFlag = true;
7763 break;
7764 }
7765 }
7766 }while (false);
7767
7768 if (err) {
7769 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7770 return false;
7771 }
7772 return true;
7773 }
7774
7775 bool
7776 IOPMrootDomain::checkSystemSleepEnabled( void )
7777 {
7778 return checkSystemSleepAllowed(0, 0);
7779 }
7780
7781 bool
7782 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7783 {
7784 ASSERT_GATED();
7785 return checkSystemSleepAllowed(1, sleepReason);
7786 }
7787
7788 //******************************************************************************
7789 // checkSystemCanSustainFullWake
7790 //******************************************************************************
7791
7792 bool
7793 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7794 {
7795 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7796 // Low battery wake, or received a low battery notification
7797 // while system is awake. This condition will persist until
7798 // the following wake.
7799 return false;
7800 }
7801
7802 if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7803 // Graphics state is unknown and external display might not be probed.
7804 // Do not incorporate state that requires graphics to be in max power
7805 // such as desktopMode or clamshellDisabled.
7806
7807 if (!acAdaptorConnected) {
7808 DLOG("full wake check: no AC\n");
7809 return false;
7810 }
7811 }
7812 return true;
7813 }
7814
7815 //******************************************************************************
7816 // checkSystemCanAbortIdleSleep
7817 //******************************************************************************
7818
7819 bool
7820 IOPMrootDomain::checkSystemCanAbortIdleSleep( void )
7821 {
7822 bool abortableSleepType = ((lastSleepReason == kIOPMSleepReasonIdle)
7823 || (lastSleepReason == 0));
7824 return idleSleepRevertible && abortableSleepType;
7825 }
7826
7827 //******************************************************************************
7828 // considerRunMode
7829 // consider the driver for AOT power on via the runmode mask
7830 //******************************************************************************
7831
7832 int32_t
7833 IOPMrootDomain::considerRunMode(IOService * service, uint64_t pmDriverClass)
7834 {
7835 int32_t promote;
7836
7837 if ((0 == _aotRunMode) || (service == this)) {
7838 // neutral
7839 return 0;
7840 }
7841 promote = (0 != (_aotRunMode & pmDriverClass)) ? 1 : -1;
7842 if (promote > 0) {
7843 IOLog("IOPMRD: %s 0x%llx runmode to %s\n", service->getName(), pmDriverClass, (promote < 0) ? "OFF" : "ON");
7844 }
7845 return promote;
7846 }
7847
7848 //******************************************************************************
7849 // attemptIdleSleepAbort
7850 //******************************************************************************
7851
7852 bool
7853 IOPMrootDomain::attemptIdleSleepAbort( void )
7854 {
7855 if (!gIOPMWorkLoop->inGate()) {
7856 bool ret = gIOPMWorkLoop->runAction(
7857 OSMemberFunctionCast(IOWorkLoop::Action, this,
7858 &IOPMrootDomain::attemptIdleSleepAbort),
7859 this);
7860 return ret;
7861 }
7862
7863 bool canAbort = checkSystemCanAbortIdleSleep();
7864 if (canAbort) {
7865 cancelIdlePowerDownSync();
7866 } else if (lastSleepReason == kIOPMSleepReasonIdle) {
7867 scheduleImmediateDebugWake();
7868 }
7869
7870 return canAbort;
7871 }
7872
7873 //******************************************************************************
7874 // setIdleSleepRevertible
7875 //******************************************************************************
7876
7877 void
7878 IOPMrootDomain::setIdleSleepRevertible( bool revertible )
7879 {
7880 idleSleepRevertible = revertible;
7881 }
7882
7883 //******************************************************************************
7884 // mustHibernate
7885 //******************************************************************************
7886
7887 #if HIBERNATION
7888
7889 bool
7890 IOPMrootDomain::mustHibernate( void )
7891 {
7892 return lowBatteryCondition || thermalWarningState;
7893 }
7894
7895 #endif /* HIBERNATION */
7896
7897 //******************************************************************************
7898 // AOT
7899 //******************************************************************************
7900
7901 // Tables for accumulated days in year by month, latter used for leap years
7902
7903 static const unsigned int daysbymonth[] =
7904 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7905
7906 static const unsigned int lydaysbymonth[] =
7907 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7908
7909 static int __unused
7910 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7911 {
7912 const unsigned int * dbm = daysbymonth;
7913 clock_sec_t n, x, y, z;
7914
7915 // Calculate seconds, minutes and hours
7916
7917 n = secs % (24 * 3600);
7918 dt->second = n % 60;
7919 n /= 60;
7920 dt->minute = n % 60;
7921 dt->hour = (typeof(dt->hour))(n / 60);
7922
7923 // Calculate day of week
7924
7925 n = secs / (24 * 3600);
7926 // dt->dayWeek = (n + 4) % 7;
7927
7928 // Calculate year
7929 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7930 // to days since 1/1/1968 to start on 4 year cycle, beginning
7931 // on a leap year.
7932
7933 n += (366 + 365);
7934
7935 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7936 // Valid before 2100, since 2100 is not a leap year.
7937
7938 x = n / 1461; // number of 4 year cycles
7939 y = n % 1461; // days into current 4 year cycle
7940 z = 1968 + (4 * x);
7941
7942 // Add in years in the current 4 year cycle
7943
7944 if (y >= 366) {
7945 y -= 366; // days after the leap year
7946 n = y % 365; // days into the current year
7947 z += (1 + y / 365); // years after the past 4-yr cycle
7948 } else {
7949 n = y;
7950 dbm = lydaysbymonth;
7951 }
7952 if (z > 2099) {
7953 return 0;
7954 }
7955
7956 dt->year = (typeof(dt->year))z;
7957
7958 // Adjust remaining days value to start at 1
7959
7960 n += 1;
7961
7962 // Calculate month
7963
7964 for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7965 continue;
7966 }
7967 dt->month = (typeof(dt->month))x;
7968
7969 // Calculate day of month
7970
7971 dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7972
7973 return 1;
7974 }
7975
7976 static clock_sec_t
7977 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7978 {
7979 const unsigned int * dbm = daysbymonth;
7980 long y, secs, days;
7981
7982 if (dt->year < 1970 || dt->month > 12) {
7983 return 0;
7984 }
7985
7986 // Seconds elapsed in the current day
7987
7988 secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7989
7990 // Number of days from 1/1/70 to beginning of current year
7991 // Account for extra day every 4 years starting at 1973
7992
7993 y = dt->year - 1970;
7994 days = (y * 365) + ((y + 1) / 4);
7995
7996 // Change table if current year is a leap year
7997
7998 if ((dt->year % 4) == 0) {
7999 dbm = lydaysbymonth;
8000 }
8001
8002 // Add in days elapsed in the current year
8003
8004 days += (dt->day - 1) + dbm[dt->month - 1];
8005
8006 // Add accumulated days to accumulated seconds
8007
8008 secs += 24 * 3600 * days;
8009
8010 return secs;
8011 }
8012
8013 unsigned long
8014 IOPMrootDomain::getRUN_STATE(void)
8015 {
8016 return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
8017 }
8018
8019 bool
8020 IOPMrootDomain::isAOTMode()
8021 {
8022 return _aotNow;
8023 }
8024
8025 bool
8026 IOPMrootDomain::isLPWMode()
8027 {
8028 return gLPWFlags && currentOrPendingPowerState(AOT_STATE);
8029 }
8030
8031 bool
8032 IOPMIsAOTMode(void)
8033 {
8034 return gIOPMRootDomain && gIOPMRootDomain->isAOTMode();
8035 }
8036 bool
8037 IOPMIsLPWMode(void)
8038 {
8039 return gIOPMRootDomain && gIOPMRootDomain->isLPWMode();
8040 }
8041
8042 void
8043 IOPMNetworkStackFullWake(uint64_t flags, const char * reason)
8044 {
8045 assert(kIOPMNetworkStackFullWakeFlag == flags);
8046 assert(gIOPMRootDomain);
8047 gIOPMRootDomain->claimSystemWakeEvent(gIOPMRootDomain, kIOPMWakeEventAOTExit, reason, NULL);
8048 }
8049
8050 IOReturn
8051 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
8052 {
8053 if (kIOPMAOTModeCycle & _aotMode) {
8054 return kIOReturnSuccess;
8055 }
8056 return _setWakeTime(wakeContinuousTime);
8057 }
8058
8059 IOReturn
8060 IOPMrootDomain::_setWakeTime(uint64_t wakeContinuousTime)
8061 {
8062 clock_sec_t nowsecs, wakesecs;
8063 clock_usec_t nowmicrosecs, wakemicrosecs;
8064 uint64_t nowAbs, wakeAbs;
8065
8066 if (!_aotMode) {
8067 return kIOReturnNotReady;
8068 }
8069
8070 clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
8071 wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
8072 if (wakeAbs < nowAbs) {
8073 printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
8074 wakeAbs = nowAbs;
8075 }
8076 wakeAbs -= nowAbs;
8077 absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
8078
8079 wakesecs += nowsecs;
8080 wakemicrosecs += nowmicrosecs;
8081 if (wakemicrosecs >= USEC_PER_SEC) {
8082 wakesecs++;
8083 wakemicrosecs -= USEC_PER_SEC;
8084 }
8085 if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
8086 wakesecs++;
8087 }
8088
8089 IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
8090
8091 if (_aotWakeTimeContinuous != wakeContinuousTime) {
8092 _aotWakeTimeContinuous = wakeContinuousTime;
8093 IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
8094 }
8095 _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
8096 _aotWakeTimeUTC = wakesecs;
8097
8098 return kIOReturnSuccess;
8099 }
8100
8101 // assumes WAKEEVENT_LOCK
8102 bool
8103 IOPMrootDomain::aotShouldExit(bool software)
8104 {
8105 bool exitNow = false;
8106 const char * reason = "";
8107
8108 if (!_aotNow) {
8109 return false;
8110 }
8111
8112 if (software) {
8113 exitNow = true;
8114 _aotMetrics->softwareRequestCount++;
8115 reason = "software request";
8116 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
8117 exitNow = true;
8118 reason = gWakeReasonString;
8119 } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
8120 clock_sec_t sec;
8121 clock_usec_t usec;
8122 clock_get_calendar_microtime(&sec, &usec);
8123 if (_calendarWakeAlarmUTC <= sec) {
8124 exitNow = true;
8125 _aotMetrics->rtcAlarmsCount++;
8126 reason = "user alarm";
8127 }
8128 }
8129 if (exitNow) {
8130 _aotPendingFlags |= kIOPMWakeEventAOTExit;
8131 IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
8132 reason,
8133 _aotMetrics->sleepCount,
8134 _aotMetrics->possibleCount,
8135 _aotMetrics->confirmedPossibleCount,
8136 _aotMetrics->rejectedPossibleCount,
8137 _aotMetrics->expiredPossibleCount,
8138 _aotMetrics->noTimeSetCount,
8139 _aotMetrics->rtcAlarmsCount);
8140 }
8141 return exitNow;
8142 }
8143
8144 void
8145 IOPMrootDomain::aotExit(bool cps)
8146 {
8147 uint32_t savedMessageMask;
8148
8149 ASSERT_GATED();
8150 _aotNow = false;
8151 _aotRunMode = 0;
8152 _aotReadyToFullWake = false;
8153 if (_aotTimerScheduled) {
8154 _aotTimerES->cancelTimeout();
8155 _aotTimerScheduled = false;
8156 }
8157 updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
8158
8159 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
8160 _aotLastWakeTime = 0;
8161 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
8162 WAKEEVENT_LOCK();
8163 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
8164 gWakeReasonString,
8165 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
8166 WAKEEVENT_UNLOCK();
8167 }
8168
8169 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
8170
8171 // Preserve the message mask since a system wake transition
8172 // may have already started and initialized the mask.
8173 savedMessageMask = _systemMessageClientMask;
8174 _systemMessageClientMask = kSystemMessageClientLegacyApp;
8175 tellClients(kIOMessageSystemWillPowerOn);
8176 _systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
8177
8178 if (cps) {
8179 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
8180 }
8181 }
8182
8183 void
8184 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
8185 {
8186 bool exitNow;
8187
8188 IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
8189
8190 WAKEEVENT_LOCK();
8191 exitNow = aotShouldExit(false);
8192 if (timer != NULL) {
8193 _aotTimerScheduled = false;
8194 }
8195 WAKEEVENT_UNLOCK();
8196 if (exitNow) {
8197 aotExit(true);
8198 } else {
8199 #if 0
8200 if (_aotLingerTime) {
8201 uint64_t deadline;
8202 IOLog("aot linger before sleep\n");
8203 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
8204 clock_delay_until(deadline);
8205 }
8206 #endif
8207 privateSleepSystem(kIOPMSleepReasonSoftware);
8208 }
8209 }
8210
8211 //******************************************************************************
8212 // adjustPowerState
8213 //
8214 // Conditions that affect our wake/sleep decision has changed.
8215 // If conditions dictate that the system must remain awake, clamp power
8216 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
8217 // is TRUE, then remove the power clamp and allow the power state to drop
8218 // to SLEEP_STATE.
8219 //******************************************************************************
8220
8221 void
8222 IOPMrootDomain::adjustPowerState( bool sleepASAP )
8223 {
8224 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d, _aotNow %d\n",
8225 getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled, _aotNow);
8226
8227 ASSERT_GATED();
8228
8229 if (_aotNow) {
8230 bool exitNow;
8231
8232 if (AOT_STATE != getPowerState()) {
8233 return;
8234 }
8235 WAKEEVENT_LOCK();
8236 exitNow = aotShouldExit(false);
8237 if (!exitNow
8238 && !_aotTimerScheduled
8239 && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
8240 _aotTimerScheduled = true;
8241 _aotTimerES->setTimeout(_aotLingerTime, kMillisecondScale);
8242 }
8243 WAKEEVENT_UNLOCK();
8244 if (exitNow) {
8245 aotExit(true);
8246 } else {
8247 _aotReadyToFullWake = true;
8248 if (!_aotTimerScheduled) {
8249 if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
8250 // Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
8251 // Doing so will result in the sleep being cancelled anyway,
8252 // but this check avoids unnecessary thrashing in the power state engine.
8253 return;
8254 }
8255 privateSleepSystem(kIOPMSleepReasonSoftware);
8256 }
8257 }
8258 return;
8259 }
8260
8261 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
8262 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
8263 } else if (sleepASAP) {
8264 changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
8265 }
8266 }
8267
8268 void
8269 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
8270 {
8271 if (powerOn) {
8272 if (!checkSystemCanSustainFullWake()) {
8273 DLOG("System cannot sustain full wake\n");
8274 return;
8275 }
8276
8277 // Force wrangler to max power state. If system is in dark wake
8278 // this alone won't raise the wrangler's power state.
8279 if (wrangler) {
8280 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
8281 }
8282
8283 // System in dark wake, always requesting full wake should
8284 // not have any bad side-effects, even if the request fails.
8285
8286 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8287 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
8288 requestFullWake( kFullWakeReasonDisplayOn );
8289 }
8290 } else {
8291 // Relenquish desire to power up display.
8292 // Must first transition to state 1 since wrangler doesn't
8293 // power off the displays at state 0. At state 0 the root
8294 // domain is removed from the wrangler's power client list.
8295 if (wrangler) {
8296 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
8297 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
8298 }
8299 }
8300 }
8301
8302 TUNABLE(bool, test_sleep_in_vm, "test_sleep_in_vm", false);
8303
8304 //******************************************************************************
8305 // dispatchPowerEvent
8306 //
8307 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
8308 //******************************************************************************
8309
8310 void
8311 IOPMrootDomain::dispatchPowerEvent(
8312 uint32_t event, void * arg0, uint64_t arg1 )
8313 {
8314 ASSERT_GATED();
8315
8316 switch (event) {
8317 case kPowerEventFeatureChanged:
8318 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8319 messageClients(kIOPMMessageFeatureChange, this);
8320 break;
8321
8322 case kPowerEventReceivedPowerNotification:
8323 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8324 handlePowerNotification((UInt32)(uintptr_t) arg0 );
8325 break;
8326
8327 case kPowerEventSystemBootCompleted:
8328 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8329 if (systemBooting) {
8330 systemBooting = false;
8331
8332 if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
8333 DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
8334 if (test_sleep_in_vm && gSleepDisabledFlag) {
8335 DLOG("Clearing gSleepDisabledFlag due to test_sleep_in_vm boot-arg\n");
8336 gSleepDisabledFlag = 0;
8337 }
8338 }
8339
8340 if (lowBatteryCondition || thermalEmergencyState) {
8341 if (lowBatteryCondition) {
8342 privateSleepSystem(kIOPMSleepReasonLowPower);
8343 } else {
8344 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8345 }
8346 // The rest is unnecessary since the system is expected
8347 // to sleep immediately. The following wake will update
8348 // everything.
8349 break;
8350 }
8351
8352 sleepWakeDebugMemAlloc();
8353 saveFailureData2File();
8354
8355 // If lid is closed, re-send lid closed notification
8356 // now that booting is complete.
8357 if (clamshellClosed) {
8358 handlePowerNotification(kLocalEvalClamshellCommand);
8359 }
8360 evaluatePolicy( kStimulusAllowSystemSleepChanged );
8361 }
8362 break;
8363
8364 case kPowerEventSystemShutdown:
8365 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8366 if (kOSBooleanTrue == (OSBoolean *) arg0) {
8367 /* We set systemShutdown = true during shutdown
8368 * to prevent sleep at unexpected times while loginwindow is trying
8369 * to shutdown apps and while the OS is trying to transition to
8370 * complete power of.
8371 *
8372 * Set to true during shutdown, as soon as loginwindow shows
8373 * the "shutdown countdown dialog", through individual app
8374 * termination, and through black screen kernel shutdown.
8375 */
8376 systemShutdown = true;
8377 } else {
8378 /*
8379 * A shutdown was initiated, but then the shutdown
8380 * was cancelled, clearing systemShutdown to false here.
8381 */
8382 systemShutdown = false;
8383 }
8384 break;
8385
8386 case kPowerEventUserDisabledSleep:
8387 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8388 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8389 break;
8390
8391 case kPowerEventRegisterSystemCapabilityClient:
8392 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8393
8394 // reset() handles the arg0 == nullptr case for us
8395 systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8396 /* intentional fall-through */
8397 [[clang::fallthrough]];
8398
8399 case kPowerEventRegisterKernelCapabilityClient:
8400 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8401 if (!_joinedCapabilityClients) {
8402 _joinedCapabilityClients = OSSet::withCapacity(8);
8403 }
8404 if (arg0) {
8405 OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8406 if (_joinedCapabilityClients) {
8407 _joinedCapabilityClients->setObject(notify.get());
8408 synchronizePowerTree( kIOPMSyncNoChildNotify );
8409 }
8410 }
8411 break;
8412
8413 case kPowerEventPolicyStimulus:
8414 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8415 if (arg0) {
8416 int stimulus = (int)(uintptr_t) arg0;
8417 evaluatePolicy(stimulus, (uint32_t) arg1);
8418 }
8419 break;
8420
8421 case kPowerEventAssertionCreate:
8422 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8423 if (pmAssertions) {
8424 pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8425 }
8426 break;
8427
8428
8429 case kPowerEventAssertionRelease:
8430 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8431 if (pmAssertions) {
8432 pmAssertions->handleReleaseAssertion(arg1);
8433 }
8434 break;
8435
8436 case kPowerEventAssertionSetLevel:
8437 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8438 if (pmAssertions) {
8439 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8440 }
8441 break;
8442
8443 case kPowerEventQueueSleepWakeUUID:
8444 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8445 handleQueueSleepWakeUUID((OSObject *)arg0);
8446 break;
8447 case kPowerEventPublishSleepWakeUUID:
8448 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8449 handlePublishSleepWakeUUID((bool)arg0);
8450 break;
8451
8452 case kPowerEventSetDisplayPowerOn:
8453 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8454 if (arg1 != 0) {
8455 displayPowerOnRequested = true;
8456 } else {
8457 displayPowerOnRequested = false;
8458 }
8459 handleSetDisplayPowerOn(displayPowerOnRequested);
8460 break;
8461
8462 case kPowerEventPublishWakeType:
8463 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8464
8465 // Don't replace wake type property if already set
8466 if ((arg0 == gIOPMWakeTypeUserKey) ||
8467 !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8468 const char * wakeType = NULL;
8469
8470 if (arg0 == gIOPMWakeTypeUserKey) {
8471 requestUserActive(this, "WakeTypeUser");
8472 wakeType = kIOPMRootDomainWakeTypeUser;
8473 } else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8474 if (!(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
8475 requestUserActive(this, "WakeTypeAlarm");
8476 }
8477 wakeType = kIOPMRootDomainWakeTypeAlarm;
8478 } else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8479 darkWakeSleepService = true;
8480 wakeType = kIOPMRootDomainWakeTypeSleepService;
8481 } else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8482 wakeType = kIOPMRootDomainWakeTypeMaintenance;
8483 }
8484
8485 if (wakeType) {
8486 setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8487 }
8488 }
8489 break;
8490
8491 case kPowerEventAOTEvaluate:
8492 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8493 if (_aotReadyToFullWake) {
8494 aotEvaluate(NULL);
8495 }
8496 break;
8497 case kPowerEventRunModeRequest:
8498 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8499 // arg1 == runModeMask
8500 handleRequestRunMode(arg1);
8501 break;
8502 }
8503 }
8504
8505 //******************************************************************************
8506 // systemPowerEventOccurred
8507 //
8508 // The power controller is notifying us of a hardware-related power management
8509 // event that we must handle.
8510 //
8511 // systemPowerEventOccurred covers the same functionality that
8512 // receivePowerNotification does; it simply provides a richer API for conveying
8513 // more information.
8514 //******************************************************************************
8515
8516 IOReturn
8517 IOPMrootDomain::systemPowerEventOccurred(
8518 const OSSymbol *event,
8519 uint32_t intValue)
8520 {
8521 IOReturn attempt = kIOReturnSuccess;
8522 OSSharedPtr<OSNumber> newNumber;
8523
8524 if (!event) {
8525 return kIOReturnBadArgument;
8526 }
8527
8528 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8529 if (!newNumber) {
8530 return kIOReturnInternalError;
8531 }
8532
8533 attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8534
8535 return attempt;
8536 }
8537
8538 void
8539 IOPMrootDomain::setThermalState(OSObject *value)
8540 {
8541 OSNumber * num;
8542
8543 if (gIOPMWorkLoop->inGate() == false) {
8544 gIOPMWorkLoop->runAction(
8545 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8546 (OSObject *)this,
8547 (void *)value);
8548
8549 return;
8550 }
8551 if (value && (num = OSDynamicCast(OSNumber, value))) {
8552 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8553 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8554 }
8555 }
8556
8557 IOReturn
8558 IOPMrootDomain::systemPowerEventOccurred(
8559 const OSSymbol *event,
8560 OSObject *value)
8561 {
8562 OSSharedPtr<OSDictionary> thermalsDict;
8563 bool shouldUpdate = true;
8564
8565 if (!event || !value) {
8566 return kIOReturnBadArgument;
8567 }
8568
8569 // LOCK
8570 // We reuse featuresDict Lock because it already exists and guards
8571 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
8572 // of stepping on that lock.
8573 if (featuresDictLock) {
8574 IOLockLock(featuresDictLock);
8575 }
8576
8577 OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8578 OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8579
8580 if (origThermalsDict) {
8581 thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8582 } else {
8583 thermalsDict = OSDictionary::withCapacity(1);
8584 }
8585
8586 if (!thermalsDict) {
8587 shouldUpdate = false;
8588 goto exit;
8589 }
8590
8591 thermalsDict->setObject(event, value);
8592
8593 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8594
8595 exit:
8596 // UNLOCK
8597 if (featuresDictLock) {
8598 IOLockUnlock(featuresDictLock);
8599 }
8600
8601 if (shouldUpdate) {
8602 if (event &&
8603 event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8604 setThermalState(value);
8605 }
8606 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8607 }
8608
8609 return kIOReturnSuccess;
8610 }
8611
8612 //******************************************************************************
8613 // receivePowerNotification
8614 //
8615 // The power controller is notifying us of a hardware-related power management
8616 // event that we must handle. This may be a result of an 'environment' interrupt
8617 // from the power mgt micro.
8618 //******************************************************************************
8619
8620 IOReturn
8621 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8622 {
8623 if (msg & kIOPMPowerButton) {
8624 uint32_t currentPhase = pmTracer->getTracePhase();
8625 if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8626 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8627 swd_flags |= SWD_PWR_BTN_STACKSHOT;
8628 thread_call_enter(powerButtonDown);
8629 } else {
8630 DEBUG_LOG("power button pressed when system is up\n");
8631 }
8632 } else if (msg & kIOPMPowerButtonUp) {
8633 if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8634 swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8635 thread_call_enter(powerButtonUp);
8636 }
8637 } else {
8638 pmPowerStateQueue->submitPowerEvent(
8639 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8640 }
8641 return kIOReturnSuccess;
8642 }
8643
8644 void
8645 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8646 {
8647 bool eval_clamshell = false;
8648 bool eval_clamshell_alarm = false;
8649
8650 ASSERT_GATED();
8651
8652 /*
8653 * Local (IOPMrootDomain only) eval clamshell command
8654 */
8655 if (msg & kLocalEvalClamshellCommand) {
8656 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8657 eval_clamshell_alarm = true;
8658
8659 // reset isRTCAlarmWake. This evaluation should happen only once
8660 // on RTC/Alarm wake. Any clamshell events after wake should follow
8661 // the regular evaluation
8662 isRTCAlarmWake = false;
8663 } else {
8664 eval_clamshell = true;
8665 }
8666 }
8667
8668 /*
8669 * Overtemp
8670 */
8671 if (msg & kIOPMOverTemp) {
8672 DLOG("Thermal overtemp message received!\n");
8673 thermalEmergencyState = true;
8674 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8675 }
8676
8677 /*
8678 * Forward DW thermal notification to client, if system is not going to sleep
8679 */
8680 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8681 DLOG("DarkWake thermal limits message received!\n");
8682 messageClients(kIOPMMessageDarkWakeThermalEmergency);
8683 }
8684
8685 /*
8686 * Sleep Now!
8687 */
8688 if (msg & kIOPMSleepNow) {
8689 privateSleepSystem(kIOPMSleepReasonSoftware);
8690 }
8691
8692 /*
8693 * Power Emergency
8694 */
8695 if (msg & kIOPMPowerEmergency) {
8696 DLOG("Received kIOPMPowerEmergency");
8697 #if HIBERNATION && defined(__arm64__)
8698 if (!ml_is_secure_hib_supported() || ldmHibernateDisable) {
8699 // Wait for the next low battery notification if the system state is
8700 // in transition.
8701 if ((_systemTransitionType == kSystemTransitionNone) &&
8702 CAP_CURRENT(kIOPMSystemCapabilityCPU) &&
8703 !systemBooting && !systemShutdown && !gWillShutdown) {
8704 // Setting lowBatteryCondition will prevent system sleep
8705 lowBatteryCondition = true;
8706
8707 // Notify userspace to initiate system shutdown
8708 DLOG("Initiating userspace shutdown ml_is_secure_hib_supported %d lockdownMode %d", ml_is_secure_hib_supported(), ldmHibernateDisable);
8709 messageClients(kIOPMMessageRequestSystemShutdown);
8710 }
8711 } else {
8712 lowBatteryCondition = true;
8713 privateSleepSystem(kIOPMSleepReasonLowPower);
8714 }
8715 #else /* HIBERNATION && defined(__arm64__) */
8716 lowBatteryCondition = true;
8717 privateSleepSystem(kIOPMSleepReasonLowPower);
8718 #endif /* HIBERNATION && defined(__arm64__) */
8719 }
8720
8721 /*
8722 * Clamshell OPEN
8723 */
8724 if (msg & kIOPMClamshellOpened) {
8725 DLOG("Clamshell opened\n");
8726 // Received clamshel open message from clamshell controlling driver
8727 // Update our internal state and tell general interest clients
8728 clamshellClosed = false;
8729 clamshellExists = true;
8730
8731 // Don't issue a hid tickle when lid is open and polled on wake
8732 if (msg & kIOPMSetValue) {
8733 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8734 reportUserInput();
8735 }
8736
8737 // Tell PMCPU
8738 informCPUStateChange(kInformLid, 0);
8739
8740 // Tell general interest clients
8741 sendClientClamshellNotification();
8742
8743 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
8744 || (lastSleepReason == kIOPMSleepReasonIdle)
8745 || (lastSleepReason == kIOPMSleepReasonMaintenance));
8746 if (aborting) {
8747 userActivityCount++;
8748 }
8749 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8750 }
8751
8752 /*
8753 * Clamshell CLOSED
8754 * Send the clamshell interest notification since the lid is closing.
8755 */
8756 if (msg & kIOPMClamshellClosed) {
8757 if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8758 clamshellClosed && clamshellExists) {
8759 DLOG("Ignoring redundant Clamshell close event\n");
8760 } else {
8761 DLOG("Clamshell closed\n");
8762 // Received clamshel open message from clamshell controlling driver
8763 // Update our internal state and tell general interest clients
8764 clamshellClosed = true;
8765 clamshellExists = true;
8766
8767 // Ignore all following clamshell close events until the clamshell
8768 // is opened or the system sleeps. When a clamshell close triggers
8769 // a system wake, the lid driver may send us two clamshell close
8770 // events, one for the clamshell close event itself, and a second
8771 // close event when the driver polls the lid state on wake.
8772 clamshellIgnoreClose = true;
8773
8774 // Tell PMCPU
8775 informCPUStateChange(kInformLid, 1);
8776
8777 // Tell general interest clients
8778 sendClientClamshellNotification();
8779
8780 // And set eval_clamshell = so we can attempt
8781 eval_clamshell = true;
8782 }
8783 }
8784
8785 /*
8786 * Set Desktop mode (sent from graphics)
8787 *
8788 * -> reevaluate lid state
8789 */
8790 if (msg & kIOPMSetDesktopMode) {
8791 desktopMode = (0 != (msg & kIOPMSetValue));
8792 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8793 DLOG("Desktop mode %d\n", desktopMode);
8794
8795 sendClientClamshellNotification();
8796
8797 // Re-evaluate the lid state
8798 eval_clamshell = true;
8799 }
8800
8801 /*
8802 * AC Adaptor connected
8803 *
8804 * -> reevaluate lid state
8805 */
8806 if (msg & kIOPMSetACAdaptorConnected) {
8807 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8808 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8809
8810 // Tell CPU PM
8811 informCPUStateChange(kInformAC, !acAdaptorConnected);
8812
8813 // Tell BSD if AC is connected
8814 // 0 == external power source; 1 == on battery
8815 post_sys_powersource(acAdaptorConnected ? 0:1);
8816
8817 sendClientClamshellNotification();
8818
8819 IOUserServer::powerSourceChanged(acAdaptorConnected);
8820
8821 // Re-evaluate the lid state
8822 eval_clamshell = true;
8823
8824 // Lack of AC may have latched a display wrangler tickle.
8825 // This mirrors the hardware's USB wake event latch, where a latched
8826 // USB wake event followed by an AC attach will trigger a full wake.
8827 latchDisplayWranglerTickle( false );
8828
8829 #if HIBERNATION
8830 // AC presence will reset the standy timer delay adjustment.
8831 _standbyTimerResetSeconds = 0;
8832 #endif
8833 if (!userIsActive) {
8834 // Reset userActivityTime when power supply is changed(rdr 13789330)
8835 clock_get_uptime(&userActivityTime);
8836 }
8837 }
8838
8839 /*
8840 * Enable Clamshell (external display disappear)
8841 *
8842 * -> reevaluate lid state
8843 */
8844 if (msg & kIOPMEnableClamshell) {
8845 DLOG("Clamshell enabled\n");
8846
8847 // Re-evaluate the lid state
8848 // System should sleep on external display disappearance
8849 // in lid closed operation.
8850 if (true == clamshellDisabled) {
8851 eval_clamshell = true;
8852
8853 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8854 // Also clear kClamshellSleepDisableInternal when graphics enables
8855 // the clamshell during a full wake. When graphics is behaving as
8856 // expected, this will allow clamshell close to be honored earlier
8857 // rather than waiting for the delayed evaluation.
8858 if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8859 (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8860 CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8861 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8862
8863 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8864 // when timer expires which is harmless but useless.
8865 thread_call_cancel(fullWakeThreadCall);
8866 }
8867 #endif
8868 }
8869
8870 clamshellDisabled = false;
8871 sendClientClamshellNotification();
8872 }
8873
8874 /*
8875 * Disable Clamshell (external display appeared)
8876 * We don't bother re-evaluating clamshell state. If the system is awake,
8877 * the lid is probably open.
8878 */
8879 if (msg & kIOPMDisableClamshell) {
8880 DLOG("Clamshell disabled\n");
8881 clamshellDisabled = true;
8882 sendClientClamshellNotification();
8883 }
8884
8885 /*
8886 * Evaluate clamshell and SLEEP if appropriate
8887 */
8888 if (eval_clamshell_alarm && clamshellClosed) {
8889 if (shouldSleepOnRTCAlarmWake()) {
8890 privateSleepSystem(kIOPMSleepReasonClamshell);
8891 }
8892 } else if (eval_clamshell && clamshellClosed) {
8893 if (shouldSleepOnClamshellClosed()) {
8894 privateSleepSystem(kIOPMSleepReasonClamshell);
8895 } else {
8896 evaluatePolicy( kStimulusDarkWakeEvaluate );
8897 }
8898 }
8899
8900 if (msg & kIOPMProModeEngaged) {
8901 int newState = 1;
8902 DLOG("ProModeEngaged\n");
8903 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8904 }
8905
8906 if (msg & kIOPMProModeDisengaged) {
8907 int newState = 0;
8908 DLOG("ProModeDisengaged\n");
8909 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8910 }
8911 }
8912
8913 //******************************************************************************
8914 // evaluatePolicy
8915 //
8916 // Evaluate root-domain policy in response to external changes.
8917 //******************************************************************************
8918
8919 void
8920 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8921 {
8922 union {
8923 struct {
8924 int idleSleepEnabled : 1;
8925 int idleSleepDisabled : 1;
8926 int displaySleep : 1;
8927 int sleepDelayChanged : 1;
8928 int evaluateDarkWake : 1;
8929 int adjustPowerState : 1;
8930 int userBecameInactive : 1;
8931 int displaySleepEntry : 1;
8932 } bit;
8933 uint32_t u32;
8934 } flags;
8935
8936
8937 ASSERT_GATED();
8938 flags.u32 = 0;
8939
8940 switch (stimulus) {
8941 case kStimulusDisplayWranglerSleep:
8942 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8943 if (!wranglerPowerOff) {
8944 // wrangler is in sleep state or lower
8945 flags.bit.displaySleep = true;
8946 }
8947 if (!wranglerAsleep) {
8948 // transition from wrangler wake to wrangler sleep
8949 flags.bit.displaySleepEntry = true;
8950 wranglerAsleep = true;
8951 }
8952 break;
8953
8954 case kStimulusDisplayWranglerWake:
8955 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8956 displayIdleForDemandSleep = false;
8957 wranglerPowerOff = false;
8958 wranglerAsleep = false;
8959 break;
8960
8961 case kStimulusEnterUserActiveState:
8962 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8963 if (_preventUserActive) {
8964 DLOG("user active dropped\n");
8965 break;
8966 }
8967 if (!userIsActive) {
8968 userIsActive = true;
8969 userWasActive = true;
8970 clock_get_uptime(&gUserActiveAbsTime);
8971
8972 // Stay awake after dropping demand for display power on
8973 if (kFullWakeReasonDisplayOn == fullWakeReason) {
8974 fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8975 DLOG("User activity while in notification wake\n");
8976 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8977 }
8978
8979 kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8980 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8981 messageClients(kIOPMMessageUserIsActiveChanged);
8982 }
8983 flags.bit.idleSleepDisabled = true;
8984 break;
8985
8986 case kStimulusLeaveUserActiveState:
8987 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8988 if (userIsActive) {
8989 clock_get_uptime(&gUserInactiveAbsTime);
8990 userIsActive = false;
8991 clock_get_uptime(&userBecameInactiveTime);
8992 flags.bit.userBecameInactive = true;
8993
8994 kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8995 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8996 messageClients(kIOPMMessageUserIsActiveChanged);
8997 }
8998 break;
8999
9000 case kStimulusAggressivenessChanged:
9001 {
9002 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9003 unsigned long aggressiveValue;
9004 uint32_t minutesToIdleSleep = 0;
9005 uint32_t minutesToDisplayDim = 0;
9006 uint32_t minutesDelta = 0;
9007
9008 // Fetch latest display and system sleep slider values.
9009 aggressiveValue = 0;
9010 getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
9011 minutesToIdleSleep = (uint32_t) aggressiveValue;
9012
9013 aggressiveValue = 0;
9014 getAggressiveness(kPMMinutesToDim, &aggressiveValue);
9015 minutesToDisplayDim = (uint32_t) aggressiveValue;
9016 DLOG("aggressiveness changed: system %u->%u, display %u\n",
9017 sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
9018
9019 DLOG("idle time -> %d ms (ena %d)\n",
9020 idleMilliSeconds, (minutesToIdleSleep != 0));
9021
9022 // How long to wait before sleeping the system once
9023 // the displays turns off is indicated by 'extraSleepDelay'.
9024
9025 if (minutesToIdleSleep > minutesToDisplayDim) {
9026 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
9027 } else if (minutesToIdleSleep == minutesToDisplayDim) {
9028 minutesDelta = 1;
9029 }
9030
9031 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
9032 idleSleepEnabled = flags.bit.idleSleepEnabled = true;
9033 }
9034
9035 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
9036 flags.bit.idleSleepDisabled = true;
9037 idleSleepEnabled = false;
9038 }
9039 #if !defined(XNU_TARGET_OS_OSX)
9040 if (0x7fffffff == minutesToIdleSleep) {
9041 minutesToIdleSleep = idleMilliSeconds / 1000;
9042 }
9043 #endif /* !defined(XNU_TARGET_OS_OSX) */
9044
9045 if (((minutesDelta != extraSleepDelay) ||
9046 (userActivityTime != userActivityTime_prev)) &&
9047 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
9048 flags.bit.sleepDelayChanged = true;
9049 }
9050
9051 if (systemDarkWake && !darkWakeToSleepASAP &&
9052 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
9053 // Reconsider decision to remain in dark wake
9054 flags.bit.evaluateDarkWake = true;
9055 }
9056
9057 sleepSlider = minutesToIdleSleep;
9058 extraSleepDelay = minutesDelta;
9059 userActivityTime_prev = userActivityTime;
9060 } break;
9061
9062 case kStimulusDemandSystemSleep:
9063 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9064 displayIdleForDemandSleep = true;
9065 if (wrangler && wranglerIdleSettings) {
9066 // Request wrangler idle only when demand sleep is triggered
9067 // from full wake.
9068 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
9069 wrangler->setProperties(wranglerIdleSettings.get());
9070 DLOG("Requested wrangler idle\n");
9071 }
9072 }
9073 // arg = sleepReason
9074 changePowerStateWithOverrideTo( SLEEP_STATE, arg );
9075 break;
9076
9077 case kStimulusAllowSystemSleepChanged:
9078 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9079 flags.bit.adjustPowerState = true;
9080 break;
9081
9082 case kStimulusDarkWakeActivityTickle:
9083 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9084 // arg == true implies real and not self generated wrangler tickle.
9085 // Update wake type on PM work loop instead of the tickle thread to
9086 // eliminate the possibility of an early tickle clobbering the wake
9087 // type set by the platform driver.
9088 if (arg == true) {
9089 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
9090 }
9091
9092 if (!darkWakeExit) {
9093 if (latchDisplayWranglerTickle(true)) {
9094 DLOG("latched tickle\n");
9095 break;
9096 }
9097
9098 darkWakeExit = true;
9099 DLOG("Requesting full wake due to dark wake activity tickle\n");
9100 requestFullWake( kFullWakeReasonLocalUser );
9101 }
9102 break;
9103
9104 case kStimulusDarkWakeEntry:
9105 case kStimulusDarkWakeReentry:
9106 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9107 // Any system transitions since the last dark wake transition
9108 // will invalid the stimulus.
9109
9110 if (arg == _systemStateGeneration) {
9111 DLOG("dark wake entry\n");
9112 systemDarkWake = true;
9113
9114 // Keep wranglerPowerOff an invariant when wrangler is absent
9115 if (wrangler) {
9116 wranglerPowerOff = true;
9117 }
9118
9119 if (kStimulusDarkWakeEntry == stimulus) {
9120 clock_get_uptime(&userBecameInactiveTime);
9121 flags.bit.evaluateDarkWake = true;
9122 if (activitySinceSleep()) {
9123 DLOG("User activity recorded while going to darkwake\n");
9124 reportUserInput();
9125 }
9126 }
9127
9128 // Always accelerate disk spindown while in dark wake,
9129 // even if system does not support/allow sleep.
9130
9131 cancelIdleSleepTimer();
9132 setQuickSpinDownTimeout();
9133 }
9134 break;
9135
9136 case kStimulusDarkWakeEvaluate:
9137 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9138 if (systemDarkWake) {
9139 flags.bit.evaluateDarkWake = true;
9140 }
9141 break;
9142
9143 case kStimulusNoIdleSleepPreventers:
9144 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9145 flags.bit.adjustPowerState = true;
9146 break;
9147 } /* switch(stimulus) */
9148
9149 if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
9150 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
9151 darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
9152 if (darkWakeToSleepASAP ||
9153 (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
9154 uint32_t newSleepReason;
9155
9156 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9157 // System was previously in full wake. Sleep reason from
9158 // full to dark already recorded in fullToDarkReason.
9159
9160 if (lowBatteryCondition) {
9161 newSleepReason = kIOPMSleepReasonLowPower;
9162 } else if (thermalEmergencyState) {
9163 newSleepReason = kIOPMSleepReasonThermalEmergency;
9164 } else {
9165 newSleepReason = fullToDarkReason;
9166 }
9167 } else {
9168 // In dark wake from system sleep.
9169
9170 if (darkWakeSleepService) {
9171 newSleepReason = kIOPMSleepReasonSleepServiceExit;
9172 } else {
9173 newSleepReason = kIOPMSleepReasonMaintenance;
9174 }
9175 }
9176
9177 if (checkSystemCanSleep(newSleepReason)) {
9178 privateSleepSystem(newSleepReason);
9179 }
9180 } else { // non-maintenance (network) dark wake
9181 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
9182 // Release power clamp, and wait for children idle.
9183 adjustPowerState(true);
9184 } else {
9185 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
9186 }
9187 }
9188 }
9189
9190 if (systemDarkWake) {
9191 // The rest are irrelevant while system is in dark wake.
9192 flags.u32 = 0;
9193 }
9194
9195 if ((flags.bit.displaySleepEntry) &&
9196 (kFullWakeReasonDisplayOn == fullWakeReason)) {
9197 // kIOPMSleepReasonNotificationWakeExit
9198 DLOG("Display sleep while in notification wake\n");
9199 changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
9200 }
9201
9202 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
9203 bool cancelQuickSpindown = false;
9204
9205 if (flags.bit.sleepDelayChanged) {
9206 // Cancel existing idle sleep timer and quick disk spindown.
9207 // New settings will be applied by the idleSleepEnabled flag
9208 // handler below if idle sleep is enabled.
9209
9210 DLOG("extra sleep timer changed\n");
9211 cancelIdleSleepTimer();
9212 cancelQuickSpindown = true;
9213 } else {
9214 DLOG("user inactive\n");
9215 }
9216
9217 if (!userIsActive && idleSleepEnabled) {
9218 startIdleSleepTimer(getTimeToIdleSleep());
9219 }
9220
9221 if (cancelQuickSpindown) {
9222 restoreUserSpinDownTimeout();
9223 }
9224 }
9225
9226 if (flags.bit.idleSleepEnabled) {
9227 DLOG("idle sleep timer enabled\n");
9228 if (!wrangler) {
9229 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
9230 startIdleSleepTimer(getTimeToIdleSleep());
9231 #else
9232 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
9233 startIdleSleepTimer( idleMilliSeconds );
9234 #endif
9235 } else {
9236 // Start idle timer if prefs now allow system sleep
9237 // and user is already inactive. Disk spindown is
9238 // accelerated upon timer expiration.
9239
9240 if (!userIsActive) {
9241 startIdleSleepTimer(getTimeToIdleSleep());
9242 }
9243 }
9244 }
9245
9246 if (flags.bit.idleSleepDisabled) {
9247 DLOG("idle sleep timer disabled\n");
9248 cancelIdleSleepTimer();
9249 restoreUserSpinDownTimeout();
9250 adjustPowerState();
9251 }
9252
9253 if (flags.bit.adjustPowerState) {
9254 bool sleepASAP = false;
9255
9256 if (!systemBooting && (0 == idleSleepPreventersCount())) {
9257 if (!wrangler) {
9258 if (kStimulusNoIdleSleepPreventers != stimulus) {
9259 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
9260 }
9261 if (idleSleepEnabled) {
9262 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
9263 if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
9264 sleepASAP = true;
9265 }
9266 #else
9267 // stay awake for at least idleMilliSeconds
9268 startIdleSleepTimer(idleMilliSeconds);
9269 #endif
9270 }
9271 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
9272 sleepASAP = true;
9273 }
9274 }
9275
9276 adjustPowerState(sleepASAP);
9277 }
9278 }
9279
9280 //******************************************************************************
9281
9282 unsigned int
9283 IOPMrootDomain::idleSleepPreventersCount()
9284 {
9285 if (_aotMode) {
9286 unsigned int count __block;
9287 count = 0;
9288 preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
9289 {
9290 count += (NULL == obj->metaCast("AppleARMBacklight"));
9291 return false;
9292 });
9293 return count;
9294 }
9295
9296 return preventIdleSleepList->getCount();
9297 }
9298
9299
9300 //******************************************************************************
9301 // requestFullWake
9302 //
9303 // Request transition from dark wake to full wake
9304 //******************************************************************************
9305
9306 void
9307 IOPMrootDomain::requestFullWake( FullWakeReason reason )
9308 {
9309 uint32_t options = 0;
9310 IOService * pciRoot = NULL;
9311 bool promotion = false;
9312
9313 // System must be in dark wake and a valid reason for entering full wake
9314 if ((kFullWakeReasonNone == reason) ||
9315 (kFullWakeReasonNone != fullWakeReason) ||
9316 (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
9317 return;
9318 }
9319
9320 // Will clear reason upon exit from full wake
9321 fullWakeReason = reason;
9322
9323 _desiredCapability |= (kIOPMSystemCapabilityGraphics |
9324 kIOPMSystemCapabilityAudio);
9325
9326 if ((kSystemTransitionWake == _systemTransitionType) &&
9327 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
9328 !darkWakePowerClamped) {
9329 // Promote to full wake while waking up to dark wake due to tickle.
9330 // PM will hold off notifying the graphics subsystem about system wake
9331 // as late as possible, so if a HID tickle does arrive, graphics can
9332 // power up from this same wake transition. Otherwise, the latency to
9333 // power up graphics on the following transition can be huge on certain
9334 // systems. However, once any power clamping has taken effect, it is
9335 // too late to promote the current dark wake transition to a full wake.
9336 _pendingCapability |= (kIOPMSystemCapabilityGraphics |
9337 kIOPMSystemCapabilityAudio);
9338
9339 // Tell the PCI parent of audio and graphics drivers to stop
9340 // delaying the child notifications. Same for root domain.
9341 pciRoot = pciHostBridgeDriver.get();
9342 willEnterFullWake();
9343 promotion = true;
9344 }
9345
9346 // Unsafe to cancel once graphics was powered.
9347 // If system woke from dark wake, the return to sleep can
9348 // be cancelled. "awake -> dark -> sleep" transition
9349 // can be cancelled also, during the "dark -> sleep" phase
9350 // *prior* to driver power down.
9351 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
9352 _pendingCapability == 0) {
9353 options |= kIOPMSyncCancelPowerDown;
9354 }
9355
9356 synchronizePowerTree(options, pciRoot);
9357
9358 if (kFullWakeReasonLocalUser == fullWakeReason) {
9359 // IOGraphics doesn't light the display even though graphics is
9360 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
9361 // So, do an explicit activity tickle
9362 if (wrangler) {
9363 wrangler->activityTickle(0, 0);
9364 }
9365 }
9366
9367 // Log a timestamp for the initial full wake request.
9368 // System may not always honor this full wake request.
9369 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9370 AbsoluteTime now;
9371 uint64_t nsec;
9372
9373 clock_get_uptime(&now);
9374 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9375 absolutetime_to_nanoseconds(now, &nsec);
9376 MSG("full wake %s (reason %u) %u ms\n",
9377 promotion ? "promotion" : "request",
9378 fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9379 }
9380 }
9381
9382 //******************************************************************************
9383 // willEnterFullWake
9384 //
9385 // System will enter full wake from sleep, from dark wake, or from dark
9386 // wake promotion. This function aggregate things that are in common to
9387 // all three full wake transitions.
9388 //
9389 // Assumptions: fullWakeReason was updated
9390 //******************************************************************************
9391
9392 void
9393 IOPMrootDomain::willEnterFullWake( void )
9394 {
9395 hibernateRetry = false;
9396 sleepToStandby = false;
9397 standbyNixed = false;
9398 resetTimers = false;
9399 sleepTimerMaintenance = false;
9400
9401 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9402
9403 _systemMessageClientMask = kSystemMessageClientPowerd |
9404 kSystemMessageClientLegacyApp;
9405
9406 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9407 // First time to attain full wake capability since the last wake
9408 _systemMessageClientMask |= kSystemMessageClientKernel;
9409
9410 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9411 setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9412 (kFullWakeReasonLocalUser == fullWakeReason) ?
9413 kOSBooleanTrue : kOSBooleanFalse);
9414 }
9415 #if HIBERNATION
9416 IOHibernateSetWakeCapabilities(_pendingCapability);
9417 #endif
9418
9419 IOService::setAdvisoryTickleEnable( true );
9420 tellClients(kIOMessageSystemWillPowerOn);
9421 preventTransitionToUserActive(false);
9422 }
9423
9424 //******************************************************************************
9425 // fullWakeDelayedWork
9426 //
9427 // System has already entered full wake. Invoked by a delayed thread call.
9428 //******************************************************************************
9429
9430 void
9431 IOPMrootDomain::fullWakeDelayedWork( void )
9432 {
9433 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9434 if (!gIOPMWorkLoop->inGate()) {
9435 gIOPMWorkLoop->runAction(
9436 OSMemberFunctionCast(IOWorkLoop::Action, this,
9437 &IOPMrootDomain::fullWakeDelayedWork), this);
9438 return;
9439 }
9440
9441 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9442 _currentCapability, _pendingCapability, _highestCapability,
9443 clamshellDisabled, clamshellSleepDisableMask);
9444
9445 if (clamshellExists &&
9446 CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9447 !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9448 if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9449 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9450 } else {
9451 // Not the initial full wake after waking from sleep.
9452 // Evaluate the clamshell for rdar://problem/9157444.
9453 receivePowerNotification(kLocalEvalClamshellCommand);
9454 }
9455 }
9456 #endif
9457 }
9458
9459 //******************************************************************************
9460 // evaluateAssertions
9461 //
9462 //******************************************************************************
9463
9464 // Bitmask of all kernel assertions that prevent system idle sleep.
9465 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9466 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9467 (kIOPMDriverAssertionReservedBit7 | \
9468 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9469
9470 void
9471 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9472 {
9473 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9474
9475 messageClients(kIOPMMessageDriverAssertionsChanged);
9476
9477 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9478 if (wrangler) {
9479 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9480
9481 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9482 wrangler->setIgnoreIdleTimer( value );
9483 }
9484 }
9485
9486 if (changedBits & kIOPMDriverAssertionCPUBit) {
9487 if (_aotNow) {
9488 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9489 }
9490 evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9491 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9492 AbsoluteTime now;
9493 clock_usec_t microsecs;
9494 clock_get_uptime(&now);
9495 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9496 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
9497 if (assertOnWakeReport) {
9498 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9499 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9500 }
9501 }
9502 }
9503
9504 if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9505 if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9506 if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9507 DLOG("PreventIdleSleep driver assertion raised\n");
9508 bool ok = updatePreventIdleSleepList(this, true);
9509 if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9510 // Cancel idle sleep if there is one in progress
9511 cancelIdlePowerDown(this);
9512 }
9513 }
9514 } else {
9515 DLOG("PreventIdleSleep driver assertion dropped\n");
9516 updatePreventIdleSleepList(this, false);
9517 }
9518 }
9519 }
9520
9521 // MARK: -
9522 // MARK: Statistics
9523
9524 //******************************************************************************
9525 // pmStats
9526 //
9527 //******************************************************************************
9528
9529 void
9530 IOPMrootDomain::pmStatsRecordEvent(
9531 int eventIndex,
9532 AbsoluteTime timestamp)
9533 {
9534 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9535 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9536 uint64_t delta;
9537 uint64_t nsec;
9538 OSSharedPtr<OSData> publishPMStats;
9539
9540 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9541
9542 absolutetime_to_nanoseconds(timestamp, &nsec);
9543
9544 switch (eventIndex) {
9545 case kIOPMStatsHibernateImageWrite:
9546 if (starting) {
9547 gPMStats.hibWrite.start = nsec;
9548 } else if (stopping) {
9549 gPMStats.hibWrite.stop = nsec;
9550 }
9551
9552 if (stopping) {
9553 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9554 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9555 }
9556 break;
9557 case kIOPMStatsHibernateImageRead:
9558 if (starting) {
9559 gPMStats.hibRead.start = nsec;
9560 } else if (stopping) {
9561 gPMStats.hibRead.stop = nsec;
9562 }
9563
9564 if (stopping) {
9565 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9566 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9567
9568 publishPMStats = OSData::withValue(gPMStats);
9569 setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9570 bzero(&gPMStats, sizeof(gPMStats));
9571 }
9572 break;
9573 }
9574 }
9575
9576 /*
9577 * Appends a record of the application response to
9578 * IOPMrootDomain::pmStatsAppResponses
9579 */
9580 void
9581 IOPMrootDomain::pmStatsRecordApplicationResponse(
9582 const OSSymbol *response,
9583 const char *name,
9584 int messageType,
9585 uint32_t delay_ms,
9586 uint64_t id,
9587 OSObject *object,
9588 IOPMPowerStateIndex powerState,
9589 bool async)
9590 {
9591 OSSharedPtr<OSDictionary> responseDescription;
9592 OSSharedPtr<OSNumber> delayNum;
9593 OSSharedPtr<OSNumber> powerCaps;
9594 OSSharedPtr<OSNumber> pidNum;
9595 OSSharedPtr<OSNumber> msgNum;
9596 OSSharedPtr<const OSSymbol> appname;
9597 OSSharedPtr<const OSSymbol> sleep;
9598 OSSharedPtr<const OSSymbol> wake;
9599 IOPMServiceInterestNotifier *notify = NULL;
9600
9601 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9602 if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9603 notify->ackTimeoutCnt++;
9604 } else {
9605 notify->ackTimeoutCnt = 0;
9606 }
9607 }
9608
9609 if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9610 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9611 return;
9612 }
9613
9614
9615 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9616 kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9617 } else if (notify) {
9618 // User space app or kernel capability client
9619 if (id) {
9620 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9621 } else {
9622 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9623 }
9624 notify->msgType = 0;
9625 }
9626
9627 responseDescription = OSDictionary::withCapacity(5);
9628 if (responseDescription) {
9629 if (response) {
9630 responseDescription->setObject(_statsResponseTypeKey.get(), response);
9631 }
9632
9633 msgNum = OSNumber::withNumber(messageType, 32);
9634 if (msgNum) {
9635 responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9636 }
9637
9638 if (!name && notify && notify->identifier) {
9639 name = notify->identifier->getCStringNoCopy();
9640 }
9641
9642 if (name && (strlen(name) > 0)) {
9643 appname = OSSymbol::withCString(name);
9644 if (appname) {
9645 responseDescription->setObject(_statsNameKey.get(), appname.get());
9646 }
9647 }
9648
9649 if (!id && notify) {
9650 id = notify->uuid0;
9651 }
9652 pidNum = OSNumber::withNumber(id, 64);
9653 if (pidNum) {
9654 responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9655 }
9656
9657 delayNum = OSNumber::withNumber(delay_ms, 32);
9658 if (delayNum) {
9659 responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9660 }
9661
9662 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9663 powerCaps = OSNumber::withNumber(powerState, 32);
9664
9665 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9666 static const char * driverCallTypes[] = {
9667 [kDriverCallInformPreChange] = "powerStateWillChangeTo",
9668 [kDriverCallInformPostChange] = "powerStateDidChangeTo",
9669 [kDriverCallSetPowerState] = "setPowerState"
9670 };
9671
9672 if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9673 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9674 name, id, driverCallTypes[messageType], (uint32_t) powerState,
9675 async ? "async " : "", delay_ms);
9676 }
9677 #endif
9678 } else {
9679 powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9680 }
9681 if (powerCaps) {
9682 responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9683 }
9684
9685 sleep = OSSymbol::withCString("Sleep");
9686 wake = OSSymbol::withCString("Wake");
9687 if (_systemTransitionType == kSystemTransitionSleep) {
9688 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9689 } else if (_systemTransitionType == kSystemTransitionWake) {
9690 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9691 } else if (_systemTransitionType == kSystemTransitionCapability) {
9692 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9693 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9694 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9695 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9696 }
9697 }
9698
9699 IOLockLock(pmStatsLock);
9700 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9701 pmStatsAppResponses->setObject(responseDescription.get());
9702 }
9703 IOLockUnlock(pmStatsLock);
9704 }
9705
9706 return;
9707 }
9708
9709 // MARK: -
9710 // MARK: PMTraceWorker
9711
9712 //******************************************************************************
9713 // TracePoint support
9714 //
9715 //******************************************************************************
9716
9717 #define kIOPMRegisterNVRAMTracePointHandlerKey \
9718 "IOPMRegisterNVRAMTracePointHandler"
9719
9720 IOReturn
9721 IOPMrootDomain::callPlatformFunction(
9722 const OSSymbol * functionName,
9723 bool waitForFunction,
9724 void * param1, void * param2,
9725 void * param3, void * param4 )
9726 {
9727 if (pmTracer && functionName &&
9728 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9729 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9730 uint32_t tracePointPhases, tracePointPCI;
9731 uint64_t statusCode;
9732
9733 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9734 pmTracer->tracePointTarget = (void *) param2;
9735 tracePointPCI = (uint32_t)(uintptr_t) param3;
9736 tracePointPhases = (uint32_t)(uintptr_t) param4;
9737 if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9738 OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9739 if (node) {
9740 OSSharedPtr<OSObject> bootRomFailureProp;
9741 bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9742 OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9743 uint32_t bootFailureCode;
9744 if (data && data->getLength() == sizeof(bootFailureCode)) {
9745 // Failure code from EFI/BootRom is a four byte structure
9746 memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9747 tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9748 }
9749 }
9750 }
9751 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9752 if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9753 MSG("Sleep failure code 0x%08x 0x%08x\n",
9754 tracePointPCI, tracePointPhases);
9755 }
9756 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9757 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9758
9759 return kIOReturnSuccess;
9760 }
9761 #if HIBERNATION
9762 else if (functionName &&
9763 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9764 if (gSleepPolicyHandler) {
9765 return kIOReturnExclusiveAccess;
9766 }
9767 if (!param1) {
9768 return kIOReturnBadArgument;
9769 }
9770 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9771 gSleepPolicyTarget = (void *) param2;
9772 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9773 return kIOReturnSuccess;
9774 }
9775 #endif
9776
9777 return super::callPlatformFunction(
9778 functionName, waitForFunction, param1, param2, param3, param4);
9779 }
9780
9781 void
9782 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9783 uintptr_t param1, uintptr_t param2, uintptr_t param3)
9784 {
9785 uint32_t code = IODBG_POWER(event);
9786 uint64_t regId = id;
9787 if (regId == 0) {
9788 regId = getRegistryEntryID();
9789 }
9790 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9791 }
9792
9793 void
9794 IOPMrootDomain::tracePoint( uint8_t point )
9795 {
9796 if (systemBooting) {
9797 return;
9798 }
9799
9800 if (kIOPMTracePointWakeCapabilityClients == point) {
9801 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9802 }
9803
9804 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9805 pmTracer->tracePoint(point);
9806 }
9807
9808 static void
9809 kext_log_putc(char c)
9810 {
9811 if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9812 return;
9813 }
9814 if (c == '(' || c == '[' || c == ' ') {
9815 c = 0;
9816 gKextNameEnd = true;
9817 }
9818
9819 gKextNameBuf[gKextNamePos++] = c;
9820 }
9821
9822 static int
9823 kext_log(const char *fmt, ...)
9824 {
9825 va_list listp;
9826
9827 va_start(listp, fmt);
9828 _doprnt(fmt, &listp, &kext_log_putc, 16);
9829 va_end(listp);
9830
9831 return 0;
9832 }
9833
9834 static OSPtr<const OSSymbol>
9835 copyKextIdentifierWithAddress(vm_address_t address)
9836 {
9837 OSSharedPtr<const OSSymbol> identifer;
9838
9839 IOLockLock(gHaltLogLock);
9840
9841 gKextNameEnd = false;
9842 gKextNamePos = 0;
9843 gKextNameBuf[0] = 0;
9844
9845 OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9846 gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9847 identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9848
9849 IOLockUnlock(gHaltLogLock);
9850
9851 return identifer;
9852 }
9853
9854 // Caller serialized using PM workloop
9855 const char *
9856 IOPMrootDomain::getNotificationClientName(OSObject *object)
9857 {
9858 IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9859 const char *clientName = "UNKNOWN";
9860
9861 if (!notifier->clientName) {
9862 // Check for user client
9863 if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9864 OSNumber *clientID = NULL;
9865 messageClient(kIOMessageCopyClientID, object, &clientID);
9866 if (clientID) {
9867 OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9868 if (string) {
9869 notifier->clientName = OSSymbol::withString(string.get());
9870 }
9871 clientID->release();
9872 }
9873 } else if (notifier->identifier) {
9874 notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9875 }
9876 }
9877
9878 if (notifier->clientName) {
9879 clientName = notifier->clientName->getCStringNoCopy();
9880 }
9881
9882 return clientName;
9883 }
9884
9885 void
9886 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9887 {
9888 IOPMServiceInterestNotifier *notifier;
9889
9890 if (systemBooting) {
9891 return;
9892 }
9893 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9894 if (!notifier) {
9895 return;
9896 }
9897
9898 if (start) {
9899 pmTracer->traceDetail(notifier->uuid0 >> 32);
9900 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9901 (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9902
9903 // Update notifier state used for response/ack logging
9904 notifier->msgIndex = msgIndex;
9905 notifier->msgAbsTime = timestamp;
9906
9907 if (msgIndex != UINT_MAX) {
9908 DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9909 } else {
9910 DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9911 }
9912
9913 assert(notifierObject == NULL);
9914 notifierThread = current_thread();
9915 notifierObject.reset(notifier, OSRetain);
9916 } else {
9917 uint64_t nsec;
9918 uint32_t delayMS;
9919
9920 SUB_ABSOLUTETIME(×tamp, ¬ifier->msgAbsTime);
9921 absolutetime_to_nanoseconds(timestamp, &nsec);
9922 delayMS = (uint32_t)(nsec / 1000000ULL);
9923 if (delayMS > notifier->maxMsgDelayMS) {
9924 notifier->maxMsgDelayMS = delayMS;
9925 }
9926
9927 assert(notifierObject == notifier);
9928 notifierObject.reset();
9929 notifierThread = NULL;
9930 }
9931 }
9932
9933 void
9934 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9935 {
9936 if (systemBooting) {
9937 return;
9938 }
9939 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9940 if (!notifier) {
9941 return;
9942 }
9943
9944 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9945 (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9946
9947 DLOG("%s[%u] ack from %s took %d ms\n",
9948 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9949 if (delay_ms > notifier->maxAckDelayMS) {
9950 notifier->maxAckDelayMS = delay_ms;
9951 }
9952 }
9953
9954 void
9955 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9956 {
9957 if (systemBooting) {
9958 return;
9959 }
9960 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9961 if (!notifier) {
9962 return;
9963 }
9964
9965 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9966 (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9967
9968 if (ack_time_us == 0) {
9969 // Client work is done and ack will not be forthcoming
9970 DLOG("%s[%u] response from %s took %d ms\n",
9971 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9972 } else {
9973 // Client needs more time and it must ack within ack_time_us
9974 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9975 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9976 }
9977 }
9978
9979 void
9980 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9981 {
9982 if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9983 return;
9984 }
9985 if (systemBooting) {
9986 return;
9987 }
9988 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9989 if (!notifier) {
9990 return;
9991 }
9992
9993 DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9994 }
9995
9996 void
9997 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9998 {
9999 if (!systemBooting) {
10000 uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
10001 pmTracer->traceDetail( detail );
10002 kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
10003 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
10004 }
10005 }
10006
10007 void
10008 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
10009 {
10010 size_t reportSize;
10011 void **report = NULL;
10012 uint32_t bktCnt;
10013 uint32_t bktSize;
10014 uint32_t *clientCnt;
10015
10016 ASSERT_GATED();
10017
10018 report = NULL;
10019 if (channel_id == kAssertDelayChID) {
10020 report = &assertOnWakeReport;
10021 bktCnt = kAssertDelayBcktCnt;
10022 bktSize = kAssertDelayBcktSize;
10023 clientCnt = &assertOnWakeClientCnt;
10024 } else if (channel_id == kSleepDelaysChID) {
10025 report = &sleepDelaysReport;
10026 bktCnt = kSleepDelaysBcktCnt;
10027 bktSize = kSleepDelaysBcktSize;
10028 clientCnt = &sleepDelaysClientCnt;
10029 } else {
10030 assert(false);
10031 return;
10032 }
10033
10034 switch (action) {
10035 case kIOReportEnable:
10036
10037 if (*report) {
10038 (*clientCnt)++;
10039 break;
10040 }
10041
10042 reportSize = HISTREPORT_BUFSIZE(bktCnt);
10043 *report = IOMallocZeroData(reportSize);
10044 if (*report == NULL) {
10045 break;
10046 }
10047 HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
10048 getRegistryEntryID(), channel_id, kIOReportCategoryPower);
10049
10050 if (channel_id == kAssertDelayChID) {
10051 assertOnWakeSecs = 0;
10052 }
10053
10054 break;
10055
10056 case kIOReportDisable:
10057 if (*clientCnt == 0) {
10058 break;
10059 }
10060 if (*clientCnt == 1) {
10061 IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
10062 *report = NULL;
10063 }
10064 (*clientCnt)--;
10065
10066 if (channel_id == kAssertDelayChID) {
10067 assertOnWakeSecs = -1; // Invalid value to prevent updates
10068 }
10069 break;
10070
10071 case kIOReportGetDimensions:
10072 if (*report) {
10073 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
10074 }
10075 break;
10076 }
10077
10078 return;
10079 }
10080
10081 IOReturn
10082 IOPMrootDomain::configureReport(IOReportChannelList *channelList,
10083 IOReportConfigureAction action,
10084 void *result,
10085 void *destination)
10086 {
10087 unsigned cnt;
10088 uint64_t configAction = (uint64_t)action;
10089
10090 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
10091 if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
10092 (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
10093 (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
10094 if (action != kIOReportGetDimensions) {
10095 continue;
10096 }
10097 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
10098 } else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
10099 (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
10100 gIOPMWorkLoop->runAction(
10101 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
10102 (OSObject *)this, (void *)channelList->channels[cnt].channel_id,
10103 (void *)configAction, (void *)result);
10104 }
10105 }
10106
10107 return super::configureReport(channelList, action, result, destination);
10108 }
10109
10110 IOReturn
10111 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
10112 {
10113 uint32_t size2cpy;
10114 void *data2cpy;
10115 void **report;
10116
10117 ASSERT_GATED();
10118
10119 report = NULL;
10120 if (ch_id == kAssertDelayChID) {
10121 report = &assertOnWakeReport;
10122 } else if (ch_id == kSleepDelaysChID) {
10123 report = &sleepDelaysReport;
10124 } else {
10125 assert(false);
10126 return kIOReturnBadArgument;
10127 }
10128
10129 if (*report == NULL) {
10130 return kIOReturnNotOpen;
10131 }
10132
10133 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
10134 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
10135 return kIOReturnOverrun;
10136 }
10137
10138 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
10139 dest->appendBytes(data2cpy, size2cpy);
10140
10141 return kIOReturnSuccess;
10142 }
10143
10144 IOReturn
10145 IOPMrootDomain::updateReport(IOReportChannelList *channelList,
10146 IOReportUpdateAction action,
10147 void *result,
10148 void *destination)
10149 {
10150 uint32_t size2cpy;
10151 void *data2cpy;
10152 uint8_t buf[SIMPLEREPORT_BUFSIZE];
10153 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
10154 unsigned cnt;
10155 uint64_t ch_id;
10156
10157 if (action != kIOReportCopyChannelData) {
10158 goto exit;
10159 }
10160
10161 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
10162 ch_id = channelList->channels[cnt].channel_id;
10163
10164 if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
10165 gIOPMWorkLoop->runAction(
10166 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
10167 (OSObject *)this, (void *)ch_id,
10168 (void *)result, (void *)dest);
10169 continue;
10170 } else if ((ch_id == kSleepCntChID) ||
10171 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
10172 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
10173 } else {
10174 continue;
10175 }
10176
10177 if (ch_id == kSleepCntChID) {
10178 SIMPLEREPORT_SETVALUE(buf, sleepCnt);
10179 } else if (ch_id == kDarkWkCntChID) {
10180 SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
10181 } else if (ch_id == kUserWkCntChID) {
10182 SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
10183 }
10184
10185 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
10186 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
10187 dest->appendBytes(data2cpy, size2cpy);
10188 }
10189
10190 exit:
10191 return super::updateReport(channelList, action, result, destination);
10192 }
10193
10194
10195 //******************************************************************************
10196 // PMTraceWorker Class
10197 //
10198 //******************************************************************************
10199
10200 #undef super
10201 #define super OSObject
10202 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
10203
10204 #define kPMBestGuessPCIDevicesCount 25
10205 #define kPMMaxRTCBitfieldSize 32
10206
10207 OSPtr<PMTraceWorker>
10208 PMTraceWorker::tracer(IOPMrootDomain * owner)
10209 {
10210 OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
10211 if (!me || !me->init()) {
10212 return NULL;
10213 }
10214
10215 DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
10216
10217 // Note that we cannot instantiate the PCI device -> bit mappings here, since
10218 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
10219 // this dictionary lazily.
10220 me->owner = owner;
10221 me->pciDeviceBitMappings = NULL;
10222 me->pmTraceWorkerLock = IOLockAlloc();
10223 me->tracePhase = kIOPMTracePointSystemUp;
10224 me->traceData32 = 0;
10225 me->loginWindowData = 0;
10226 me->coreDisplayData = 0;
10227 me->coreGraphicsData = 0;
10228 return me;
10229 }
10230
10231 void
10232 PMTraceWorker::RTC_TRACE(void)
10233 {
10234 if (tracePointHandler && tracePointTarget) {
10235 uint32_t wordA;
10236
10237 IOLockLock(pmTraceWorkerLock);
10238 wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
10239 (coreGraphicsData << 8) | tracePhase;
10240 IOLockUnlock(pmTraceWorkerLock);
10241
10242 tracePointHandler( tracePointTarget, traceData32, wordA );
10243 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
10244 }
10245 #if DEVELOPMENT || DEBUG
10246 if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
10247 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
10248 IOLock *l = IOLockAlloc();
10249 IOLockLock(l);
10250 IOLockLock(l);
10251 }
10252 #endif /* DEVELOPMENT || DEBUG */
10253 }
10254
10255 int
10256 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
10257 {
10258 OSSharedPtr<const OSSymbol> deviceName;
10259 int index = -1;
10260
10261 IOLockLock(pmTraceWorkerLock);
10262
10263 if (!pciDeviceBitMappings) {
10264 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
10265 if (!pciDeviceBitMappings) {
10266 goto exit;
10267 }
10268 }
10269
10270 // Check for bitmask overflow.
10271 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
10272 goto exit;
10273 }
10274
10275 if ((deviceName = pciDevice->copyName()) &&
10276 (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
10277 pciDeviceBitMappings->setObject(deviceName.get())) {
10278 index = pciDeviceBitMappings->getCount() - 1;
10279 _LOG("PMTrace PCI array: set object %s => %d\n",
10280 deviceName->getCStringNoCopy(), index);
10281 }
10282
10283 if (!addedToRegistry && (index >= 0)) {
10284 addedToRegistry = owner->setProperty("PCITopLevel", this);
10285 }
10286
10287 exit:
10288 IOLockUnlock(pmTraceWorkerLock);
10289 return index;
10290 }
10291
10292 bool
10293 PMTraceWorker::serialize(OSSerialize *s) const
10294 {
10295 bool ok = false;
10296 if (pciDeviceBitMappings) {
10297 IOLockLock(pmTraceWorkerLock);
10298 ok = pciDeviceBitMappings->serialize(s);
10299 IOLockUnlock(pmTraceWorkerLock);
10300 }
10301 return ok;
10302 }
10303
10304 void
10305 PMTraceWorker::tracePoint(uint8_t phase)
10306 {
10307 // clear trace detail when phase begins
10308 if (tracePhase != phase) {
10309 traceData32 = 0;
10310 }
10311
10312 tracePhase = phase;
10313
10314 DLOG("trace point 0x%02x\n", tracePhase);
10315 RTC_TRACE();
10316 }
10317
10318 void
10319 PMTraceWorker::traceDetail(uint32_t detail)
10320 {
10321 if (detail == traceData32) {
10322 return;
10323 }
10324 traceData32 = detail;
10325 RTC_TRACE();
10326 }
10327
10328 void
10329 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
10330 {
10331 switch (component) {
10332 case kIOPMLoginWindowProgress:
10333 loginWindowData = data & kIOPMLoginWindowProgressMask;
10334 break;
10335 case kIOPMCoreDisplayProgress:
10336 coreDisplayData = data & kIOPMCoreDisplayProgressMask;
10337 break;
10338 case kIOPMCoreGraphicsProgress:
10339 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
10340 break;
10341 default:
10342 return;
10343 }
10344
10345 DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
10346 RTC_TRACE();
10347 }
10348
10349 void
10350 PMTraceWorker::tracePCIPowerChange(
10351 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
10352 {
10353 uint32_t bitMask;
10354 uint32_t expectedFlag;
10355
10356 // Ignore PCI changes outside of system sleep/wake.
10357 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
10358 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
10359 return;
10360 }
10361
10362 // Only record the WillChange transition when going to sleep,
10363 // and the DidChange on the way up.
10364 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
10365 expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
10366 kIOPMDomainWillChange : kIOPMDomainDidChange;
10367 if (changeFlags != expectedFlag) {
10368 return;
10369 }
10370
10371 // Mark this device off in our bitfield
10372 if (bitNum < kPMMaxRTCBitfieldSize) {
10373 bitMask = (1 << bitNum);
10374
10375 if (kPowerChangeStart == type) {
10376 traceData32 |= bitMask;
10377 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
10378 service->getName(), bitNum, bitMask, traceData32);
10379 owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10380 } else {
10381 traceData32 &= ~bitMask;
10382 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10383 service->getName(), bitNum, bitMask, traceData32);
10384 owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10385 }
10386
10387 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10388 RTC_TRACE();
10389 }
10390 }
10391
10392 uint64_t
10393 PMTraceWorker::getPMStatusCode()
10394 {
10395 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10396 }
10397
10398 uint8_t
10399 PMTraceWorker::getTracePhase()
10400 {
10401 return tracePhase;
10402 }
10403
10404 uint32_t
10405 PMTraceWorker::getTraceData()
10406 {
10407 return traceData32;
10408 }
10409
10410 // MARK: -
10411 // MARK: PMHaltWorker
10412
10413 //******************************************************************************
10414 // PMHaltWorker Class
10415 //
10416 //******************************************************************************
10417
10418 PMHaltWorker *
10419 PMHaltWorker::worker( void )
10420 {
10421 PMHaltWorker * me;
10422 IOThread thread;
10423
10424 do {
10425 me = OSTypeAlloc( PMHaltWorker );
10426 if (!me || !me->init()) {
10427 break;
10428 }
10429
10430 me->lock = IOLockAlloc();
10431 if (!me->lock) {
10432 break;
10433 }
10434
10435 DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10436 me->retain(); // thread holds extra retain
10437 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10438 me->release();
10439 break;
10440 }
10441 thread_deallocate(thread);
10442 return me;
10443 } while (false);
10444
10445 if (me) {
10446 me->release();
10447 }
10448 return NULL;
10449 }
10450
10451 void
10452 PMHaltWorker::free( void )
10453 {
10454 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10455 if (lock) {
10456 IOLockFree(lock);
10457 lock = NULL;
10458 }
10459 return OSObject::free();
10460 }
10461
10462 void
10463 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10464 {
10465 PMHaltWorker * me = (PMHaltWorker *) arg;
10466
10467 IOLockLock( gPMHaltLock );
10468 gPMHaltBusyCount++;
10469 me->depth = gPMHaltDepth;
10470 IOLockUnlock( gPMHaltLock );
10471
10472 while (me->depth >= 0) {
10473 PMHaltWorker::work( me );
10474
10475 IOLockLock( gPMHaltLock );
10476 if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10477 // This is the last thread to finish work on this level,
10478 // inform everyone to start working on next lower level.
10479 gPMHaltDepth--;
10480 me->depth = gPMHaltDepth;
10481 gPMHaltIdleCount = 0;
10482 thread_wakeup((event_t) &gPMHaltIdleCount);
10483 } else {
10484 // One or more threads are still working on this level,
10485 // this thread must wait.
10486 me->depth = gPMHaltDepth - 1;
10487 do {
10488 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10489 } while (me->depth != gPMHaltDepth);
10490 }
10491 IOLockUnlock( gPMHaltLock );
10492 }
10493
10494 // No more work to do, terminate thread
10495 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10496 thread_wakeup( &gPMHaltDepth );
10497 me->release();
10498 }
10499
10500 void
10501 PMHaltWorker::work( PMHaltWorker * me )
10502 {
10503 OSSharedPtr<IOService> service;
10504 OSSet * inner;
10505 AbsoluteTime startTime, elapsedTime;
10506 UInt32 deltaTime;
10507 bool timeout;
10508
10509 while (true) {
10510 timeout = false;
10511
10512 // Claim an unit of work from the shared pool
10513 IOLockLock( gPMHaltLock );
10514 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10515 if (inner) {
10516 service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10517 if (service) {
10518 inner->removeObject(service.get());
10519 }
10520 }
10521 IOLockUnlock( gPMHaltLock );
10522 if (!service) {
10523 break; // no more work at this depth
10524 }
10525 clock_get_uptime(&startTime);
10526
10527 if (!service->isInactive() &&
10528 service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10529 IOLockLock(me->lock);
10530 me->startTime = startTime;
10531 me->service = service.get();
10532 me->timeout = false;
10533 IOLockUnlock(me->lock);
10534
10535 service->systemWillShutdown( gPMHaltMessageType);
10536
10537 // Wait for driver acknowledgement
10538 IOLockLock(me->lock);
10539 while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10540 IOLockSleep(me->lock, me, THREAD_UNINT);
10541 }
10542 me->service = NULL;
10543 timeout = me->timeout;
10544 IOLockUnlock(me->lock);
10545 }
10546
10547 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10548 if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10549 LOG("%s driver %s (0x%llx) took %u ms\n",
10550 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10551 "PowerOff" : "Restart",
10552 service->getName(), service->getRegistryEntryID(),
10553 (uint32_t) deltaTime );
10554 halt_log_enter("PowerOff/Restart handler completed",
10555 OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10556 elapsedTime);
10557 }
10558
10559 me->visits++;
10560 }
10561 }
10562
10563 void
10564 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10565 {
10566 UInt64 nano;
10567 AbsoluteTime startTime;
10568 AbsoluteTime endTime;
10569
10570 endTime = *now;
10571
10572 IOLockLock(me->lock);
10573 if (me->service && !me->timeout) {
10574 startTime = me->startTime;
10575 nano = 0;
10576 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10577 SUB_ABSOLUTETIME(&endTime, &startTime);
10578 absolutetime_to_nanoseconds(endTime, &nano);
10579 }
10580 if (nano > 3000000000ULL) {
10581 me->timeout = true;
10582
10583 halt_log_enter("PowerOff/Restart still waiting on handler",
10584 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10585 endTime);
10586 MSG("%s still waiting on %s\n",
10587 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart",
10588 me->service->getName());
10589 }
10590 }
10591 IOLockUnlock(me->lock);
10592 }
10593
10594 //******************************************************************************
10595 // acknowledgeSystemWillShutdown
10596 //
10597 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10598 //******************************************************************************
10599
10600 void
10601 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10602 {
10603 PMHaltWorker * worker;
10604 OSSharedPtr<OSObject> prop;
10605
10606 if (!from) {
10607 return;
10608 }
10609
10610 //DLOG("%s acknowledged\n", from->getName());
10611 prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10612 if (prop) {
10613 worker = (PMHaltWorker *) prop.get();
10614 IOLockLock(worker->lock);
10615 from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10616 thread_wakeup((event_t) worker);
10617 IOLockUnlock(worker->lock);
10618 } else {
10619 DLOG("%s acknowledged without worker property\n",
10620 from->getName());
10621 }
10622 }
10623
10624
10625 //******************************************************************************
10626 // notifySystemShutdown
10627 //
10628 // Notify all objects in PM tree that system will shutdown or restart
10629 //******************************************************************************
10630
10631 static void
10632 notifySystemShutdown( IOService * root, uint32_t messageType )
10633 {
10634 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10635 OSSharedPtr<IORegistryIterator> iter;
10636 IORegistryEntry * entry;
10637 IOService * node;
10638 OSSet * inner;
10639 OSSharedPtr<OSSet> newInner;
10640 PMHaltWorker * workers[kPMHaltMaxWorkers];
10641 AbsoluteTime deadline;
10642 unsigned int totalNodes = 0;
10643 unsigned int depth;
10644 unsigned int rootDepth;
10645 unsigned int numWorkers;
10646 unsigned int count;
10647 int waitResult;
10648 void * baseFunc;
10649 bool ok;
10650
10651 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10652
10653 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10654
10655 // Iterate the entire PM tree starting from root
10656
10657 rootDepth = root->getDepth( gIOPowerPlane );
10658 if (!rootDepth) {
10659 goto done;
10660 }
10661
10662 // debug - for repeated test runs
10663 while (PMHaltWorker::metaClass->getInstanceCount()) {
10664 IOSleep(1);
10665 }
10666
10667 if (!gPMHaltArray) {
10668 gPMHaltArray = OSArray::withCapacity(40);
10669 if (!gPMHaltArray) {
10670 goto done;
10671 }
10672 } else { // debug
10673 gPMHaltArray->flushCollection();
10674 }
10675
10676 if (!gPMHaltLock) {
10677 gPMHaltLock = IOLockAlloc();
10678 if (!gPMHaltLock) {
10679 goto done;
10680 }
10681 }
10682
10683 if (!gPMHaltClientAcknowledgeKey) {
10684 gPMHaltClientAcknowledgeKey =
10685 OSSymbol::withCStringNoCopy("PMShutdown");
10686 if (!gPMHaltClientAcknowledgeKey) {
10687 goto done;
10688 }
10689 }
10690
10691 gPMHaltMessageType = messageType;
10692
10693 // Depth-first walk of PM plane
10694
10695 iter = IORegistryIterator::iterateOver(
10696 root, gIOPowerPlane, kIORegistryIterateRecursively);
10697
10698 if (iter) {
10699 while ((entry = iter->getNextObject())) {
10700 node = OSDynamicCast(IOService, entry);
10701 if (!node) {
10702 continue;
10703 }
10704
10705 if (baseFunc ==
10706 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10707 continue;
10708 }
10709
10710 depth = node->getDepth( gIOPowerPlane );
10711 if (depth <= rootDepth) {
10712 continue;
10713 }
10714
10715 ok = false;
10716
10717 // adjust to zero based depth
10718 depth -= (rootDepth + 1);
10719
10720 // gPMHaltArray is an array of containers, each container
10721 // refers to nodes with the same depth.
10722
10723 count = gPMHaltArray->getCount();
10724 while (depth >= count) {
10725 // expand array and insert placeholders
10726 gPMHaltArray->setObject(PLACEHOLDER);
10727 count++;
10728 }
10729 count = gPMHaltArray->getCount();
10730 if (depth < count) {
10731 inner = (OSSet *)gPMHaltArray->getObject(depth);
10732 if (inner == PLACEHOLDER) {
10733 newInner = OSSet::withCapacity(40);
10734 if (newInner) {
10735 gPMHaltArray->replaceObject(depth, newInner.get());
10736 inner = newInner.get();
10737 }
10738 }
10739
10740 // PM nodes that appear more than once in the tree will have
10741 // the same depth, OSSet will refuse to add the node twice.
10742 if (inner) {
10743 ok = inner->setObject(node);
10744 }
10745 }
10746 if (!ok) {
10747 DLOG("Skipped PM node %s\n", node->getName());
10748 }
10749 }
10750 }
10751
10752 // debug only
10753 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10754 count = 0;
10755 if (inner != PLACEHOLDER) {
10756 count = inner->getCount();
10757 }
10758 DLOG("Nodes at depth %u = %u\n", i, count);
10759 }
10760
10761 // strip placeholders (not all depths are populated)
10762 numWorkers = 0;
10763 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10764 if (inner == PLACEHOLDER) {
10765 gPMHaltArray->removeObject(i);
10766 continue;
10767 }
10768 count = inner->getCount();
10769 if (count > numWorkers) {
10770 numWorkers = count;
10771 }
10772 totalNodes += count;
10773 i++;
10774 }
10775
10776 if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10777 goto done;
10778 }
10779
10780 gPMHaltBusyCount = 0;
10781 gPMHaltIdleCount = 0;
10782 gPMHaltDepth = gPMHaltArray->getCount() - 1;
10783
10784 // Create multiple workers (and threads)
10785
10786 if (numWorkers > kPMHaltMaxWorkers) {
10787 numWorkers = kPMHaltMaxWorkers;
10788 }
10789
10790 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10791 totalNodes, gPMHaltArray->getCount(), numWorkers);
10792
10793 for (unsigned int i = 0; i < numWorkers; i++) {
10794 workers[i] = PMHaltWorker::worker();
10795 }
10796
10797 // Wait for workers to exhaust all available work
10798
10799 IOLockLock(gPMHaltLock);
10800 while (gPMHaltDepth >= 0) {
10801 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10802
10803 waitResult = IOLockSleepDeadline(
10804 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10805 if (THREAD_TIMED_OUT == waitResult) {
10806 AbsoluteTime now;
10807 clock_get_uptime(&now);
10808
10809 IOLockUnlock(gPMHaltLock);
10810 for (unsigned int i = 0; i < numWorkers; i++) {
10811 if (workers[i]) {
10812 PMHaltWorker::checkTimeout(workers[i], &now);
10813 }
10814 }
10815 IOLockLock(gPMHaltLock);
10816 }
10817 }
10818 IOLockUnlock(gPMHaltLock);
10819
10820 // Release all workers
10821
10822 for (unsigned int i = 0; i < numWorkers; i++) {
10823 if (workers[i]) {
10824 workers[i]->release();
10825 }
10826 // worker also retained by it's own thread
10827 }
10828
10829 done:
10830 DLOG("%s done\n", __FUNCTION__);
10831 return;
10832 }
10833
10834 // MARK: -
10835 // MARK: Kernel Assertion
10836
10837 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10838
10839 IOPMDriverAssertionID
10840 IOPMrootDomain::createPMAssertion(
10841 IOPMDriverAssertionType whichAssertionBits,
10842 IOPMDriverAssertionLevel assertionLevel,
10843 IOService *ownerService,
10844 const char *ownerDescription)
10845 {
10846 IOReturn ret;
10847 IOPMDriverAssertionID newAssertion;
10848
10849 if (!pmAssertions) {
10850 return 0;
10851 }
10852
10853 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10854
10855 if (kIOReturnSuccess == ret) {
10856 #if (DEVELOPMENT || DEBUG)
10857 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10858 const char *serviceName = (ownerService && ownerService->reserved) ? ownerService->getName() : NULL;
10859 OSReportWithBacktrace("PMRD: createPMAssertion(0x%qx) %s (%s)", newAssertion,
10860 serviceName, ownerDescription);
10861 }
10862 #endif /* (DEVELOPMENT || DEBUG) */
10863
10864 const bool waitForWakeup = (whichAssertionBits & kIOPMDriverAssertionForceWakeupBit);
10865 if (waitForWakeup) {
10866 waitForSystemTransitionToMinPowerState(AOT_STATE);
10867 }
10868
10869 return newAssertion;
10870 } else {
10871 return 0;
10872 }
10873 }
10874
10875 IOReturn
10876 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10877 {
10878 #if (DEVELOPMENT || DEBUG)
10879 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10880 PMAssertStruct *details = pmAssertions->detailsForID(releaseAssertion, NULL);
10881 if (details) {
10882 const char *serviceName = (details->ownerService && details->ownerService->reserved) ?
10883 details->ownerService->getName() : NULL;
10884 const char *ownerString = details->ownerString ? details->ownerString->getCStringNoCopy() : NULL;
10885 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx) %s (%s)", releaseAssertion, serviceName, ownerString);
10886 } else {
10887 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx)", releaseAssertion);
10888 }
10889 }
10890 #endif /* (DEVELOPMENT || DEBUG) */
10891 if (!pmAssertions) {
10892 return kIOReturnInternalError;
10893 }
10894 return pmAssertions->releaseAssertion(releaseAssertion);
10895 }
10896
10897
10898 IOReturn
10899 IOPMrootDomain::setPMAssertionLevel(
10900 IOPMDriverAssertionID assertionID,
10901 IOPMDriverAssertionLevel assertionLevel)
10902 {
10903 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10904 }
10905
10906 IOPMDriverAssertionLevel
10907 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10908 {
10909 IOPMDriverAssertionType sysLevels;
10910
10911 if (!pmAssertions || whichAssertion == 0) {
10912 return kIOPMDriverAssertionLevelOff;
10913 }
10914
10915 sysLevels = pmAssertions->getActivatedAssertions();
10916
10917 // Check that every bit set in argument 'whichAssertion' is asserted
10918 // in the aggregate bits.
10919 if ((sysLevels & whichAssertion) == whichAssertion) {
10920 return kIOPMDriverAssertionLevelOn;
10921 } else {
10922 return kIOPMDriverAssertionLevelOff;
10923 }
10924 }
10925
10926 IOReturn
10927 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10928 {
10929 if (!pmAssertions) {
10930 return kIOReturnNotFound;
10931 }
10932
10933 return pmAssertions->setUserAssertionLevels(inLevels);
10934 }
10935
10936 IOReturn
10937 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10938 {
10939 return gIOPMWorkLoop->runActionBlock(^{
10940 if (_driverKitMatchingAssertionCount != 0) {
10941 _driverKitMatchingAssertionCount++;
10942 return kIOReturnSuccess;
10943 } else {
10944 if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
10945 // system going to sleep
10946 return kIOReturnBusy;
10947 } else {
10948 // createPMAssertion is asynchronous.
10949 // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10950 // The assertion is used so that on release, we reevaluate all assertions
10951 _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10952 if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10953 _driverKitMatchingAssertionCount = 1;
10954 return kIOReturnSuccess;
10955 } else {
10956 return kIOReturnBusy;
10957 }
10958 }
10959 }
10960 });
10961 }
10962
10963 void
10964 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10965 {
10966 gIOPMWorkLoop->runActionBlock(^{
10967 if (_driverKitMatchingAssertionCount != 0) {
10968 _driverKitMatchingAssertionCount--;
10969 if (_driverKitMatchingAssertionCount == 0) {
10970 releasePMAssertion(_driverKitMatchingAssertion);
10971 _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10972 }
10973 } else {
10974 panic("Over-release of driverkit matching assertion");
10975 }
10976 return kIOReturnSuccess;
10977 });
10978 }
10979
10980 IOReturn
10981 IOPMrootDomain::acquireDriverKitSyncedAssertion(IOService * from, IOPMDriverAssertionID * assertionID)
10982 {
10983 return gIOPMWorkLoop->runActionBlock(^{
10984 if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
10985 // system going to sleep
10986 return kIOReturnBusy;
10987 }
10988 // createPMAssertion is asynchronous.
10989 // we must also set _driverKitSyncedAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10990 // only kIOPMDriverAssertionCPUBit is used for "synced" assertion
10991 *assertionID = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, from->getName());
10992 if (*assertionID != kIOPMUndefinedDriverAssertionID) {
10993 _driverKitSyncedAssertionCount++;
10994 return kIOReturnSuccess;
10995 } else {
10996 return kIOReturnBusy;
10997 }
10998 });
10999 }
11000
11001 void
11002 IOPMrootDomain::releaseDriverKitSyncedAssertion(IOPMDriverAssertionID assertionID)
11003 {
11004 gIOPMWorkLoop->runActionBlock(^{
11005 if (_driverKitSyncedAssertionCount != 0) {
11006 _driverKitSyncedAssertionCount--;
11007 releasePMAssertion(assertionID);
11008 } else {
11009 panic("Over-release of driverkit synced assertion");
11010 }
11011 return kIOReturnSuccess;
11012 });
11013 }
11014
11015
11016 IOReturn
11017 IOPMrootDomain::createPMAssertionSafe(
11018 IOPMDriverAssertionID *assertionID,
11019 IOPMDriverAssertionType whichAssertionBits,
11020 IOPMDriverAssertionLevel assertionLevel,
11021 IOService *ownerService,
11022 const char *ownerDescription)
11023 {
11024 IOReturn ret;
11025 IOPMDriverAssertionID __block id;
11026
11027 if (!assertionID) {
11028 return kIOReturnBadArgument;
11029 }
11030
11031 // Grab workloop to check current transition
11032 ret = gIOPMWorkLoop->runActionBlock(^{
11033 if (_systemTransitionType == kSystemTransitionSleep) {
11034 return kIOReturnBusy;
11035 }
11036 id = createPMAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription);
11037 return id ? kIOReturnSuccess : kIOReturnError;
11038 });
11039
11040 if (ret == kIOReturnSuccess) {
11041 *assertionID = id;
11042 } else if (ret == kIOReturnBusy && (kIOLogPMRootDomain & gIOKitDebug)) {
11043 DLOG("assertion denied due to ongoing sleep transition (%s)\n", ownerDescription);
11044 }
11045
11046 return ret;
11047 }
11048
11049 bool
11050 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
11051 {
11052 if (pmAssertions) {
11053 pmAssertions->publishProperties();
11054 }
11055 return IOService::serializeProperties(s);
11056 }
11057
11058 OSSharedPtr<OSObject>
11059 IOPMrootDomain::copyProperty( const char * aKey) const
11060 {
11061 OSSharedPtr<OSObject> obj;
11062 obj = IOService::copyProperty(aKey);
11063
11064 if (obj) {
11065 return obj;
11066 }
11067
11068 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
11069 sizeof(kIOPMSleepWakeWdogRebootKey))) {
11070 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
11071 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
11072 } else {
11073 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
11074 }
11075 }
11076
11077 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
11078 sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
11079 if (swd_flags & SWD_VALID_LOGS) {
11080 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
11081 } else {
11082 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
11083 }
11084 }
11085
11086 /*
11087 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
11088 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
11089 * issued by DisplayWrangler on darkwake.
11090 */
11091 if (!strcmp(aKey, "DesktopMode")) {
11092 if (desktopMode) {
11093 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
11094 } else {
11095 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
11096 }
11097 }
11098 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
11099 if (displayIdleForDemandSleep) {
11100 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
11101 } else {
11102 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
11103 }
11104 }
11105
11106 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
11107 OSSharedPtr<OSArray> array;
11108 WAKEEVENT_LOCK();
11109 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
11110 OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
11111 if (collection) {
11112 array = OSDynamicPtrCast<OSArray>(collection);
11113 }
11114 }
11115 WAKEEVENT_UNLOCK();
11116 return os::move(array);
11117 }
11118
11119 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
11120 OSSharedPtr<OSArray> array;
11121 IOLockLock(pmStatsLock);
11122 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
11123 OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
11124 if (collection) {
11125 array = OSDynamicPtrCast<OSArray>(collection);
11126 }
11127 }
11128 IOLockUnlock(pmStatsLock);
11129 return os::move(array);
11130 }
11131
11132 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
11133 OSArray *idleSleepList = NULL;
11134 gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
11135 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
11136 }
11137
11138 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
11139 OSArray *systemSleepList = NULL;
11140 gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
11141 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
11142 }
11143
11144 if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
11145 OSArray *idleSleepList = NULL;
11146 gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
11147 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
11148 }
11149
11150 if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
11151 OSArray *systemSleepList = NULL;
11152 gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
11153 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
11154 }
11155 return NULL;
11156 }
11157
11158 // MARK: -
11159 // MARK: Wake Event Reporting
11160
11161 void
11162 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
11163 {
11164 WAKEEVENT_LOCK();
11165 strlcpy(outBuf, gWakeReasonString, bufSize);
11166 WAKEEVENT_UNLOCK();
11167 }
11168
11169 void
11170 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
11171 {
11172 WAKEEVENT_LOCK();
11173 strlcpy(outBuf, gShutdownReasonString, bufSize);
11174 WAKEEVENT_UNLOCK();
11175 }
11176
11177 void
11178 IOPMrootDomain::copyShutdownTime( uint64_t * time )
11179 {
11180 WAKEEVENT_LOCK();
11181 *time = gShutdownTime;
11182 WAKEEVENT_UNLOCK();
11183 }
11184
11185 //******************************************************************************
11186 // acceptSystemWakeEvents
11187 //
11188 // Private control for the acceptance of driver wake event claims.
11189 //******************************************************************************
11190
11191 void
11192 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
11193 {
11194 bool logWakeReason = false;
11195
11196 WAKEEVENT_LOCK();
11197 switch (control) {
11198 case kAcceptSystemWakeEvents_Enable:
11199 assert(_acceptSystemWakeEvents == false);
11200 if (!_systemWakeEventsArray) {
11201 _systemWakeEventsArray = OSArray::withCapacity(4);
11202 }
11203 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
11204 if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
11205 gWakeReasonString[0] = '\0';
11206 if (_systemWakeEventsArray) {
11207 _systemWakeEventsArray->flushCollection();
11208 }
11209 }
11210
11211 // Remove stale WakeType property before system sleep
11212 removeProperty(kIOPMRootDomainWakeTypeKey);
11213 removeProperty(kIOPMRootDomainWakeReasonKey);
11214 break;
11215
11216 case kAcceptSystemWakeEvents_Disable:
11217 _acceptSystemWakeEvents = false;
11218 #if defined(XNU_TARGET_OS_OSX)
11219 logWakeReason = (gWakeReasonString[0] != '\0');
11220 #else /* !defined(XNU_TARGET_OS_OSX) */
11221 logWakeReason = gWakeReasonSysctlRegistered;
11222 #if DEVELOPMENT
11223 static int panic_allowed = -1;
11224
11225 if ((panic_allowed == -1) &&
11226 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
11227 panic_allowed = 0;
11228 }
11229
11230 if (panic_allowed) {
11231 size_t i = 0;
11232 // Panic if wake reason is null or empty
11233 for (i = 0; (i < strlen(gWakeReasonString)); i++) {
11234 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
11235 break;
11236 }
11237 }
11238 if (i >= strlen(gWakeReasonString)) {
11239 panic("Wake reason is empty");
11240 }
11241 }
11242 #endif /* DEVELOPMENT */
11243 #endif /* !defined(XNU_TARGET_OS_OSX) */
11244
11245 // publish kIOPMRootDomainWakeReasonKey if not already set
11246 if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
11247 setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
11248 }
11249 break;
11250
11251 case kAcceptSystemWakeEvents_Reenable:
11252 assert(_acceptSystemWakeEvents == false);
11253 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
11254 removeProperty(kIOPMRootDomainWakeReasonKey);
11255 break;
11256 }
11257 WAKEEVENT_UNLOCK();
11258
11259 if (logWakeReason) {
11260 MSG("system wake events: %s\n", gWakeReasonString);
11261 }
11262 }
11263
11264 //******************************************************************************
11265 // claimSystemWakeEvent
11266 //
11267 // For a driver to claim a device is the source/conduit of a system wake event.
11268 //******************************************************************************
11269
11270 void
11271 IOPMrootDomain::claimSystemWakeEvent(
11272 IOService * device,
11273 IOOptionBits flags,
11274 const char * reason,
11275 OSObject * details )
11276 {
11277 OSSharedPtr<const OSSymbol> deviceName;
11278 OSSharedPtr<OSNumber> deviceRegId;
11279 OSSharedPtr<OSNumber> claimTime;
11280 OSSharedPtr<OSData> flagsData;
11281 OSSharedPtr<OSString> reasonString;
11282 OSSharedPtr<OSDictionary> dict;
11283 uint64_t timestamp;
11284 bool addWakeReason;
11285
11286 if (!device || !reason) {
11287 return;
11288 }
11289
11290 pmEventTimeStamp(×tamp);
11291
11292 uint64_t args[3] = {};
11293 strlcpy((char *)args, reason, sizeof(args));
11294 kdebugTrace(kPMLogClaimSystemWake, args[0], args[1], args[2], device->getRegistryEntryID());
11295
11296 IOOptionBits aotFlags = 0;
11297 bool needAOTEvaluate = FALSE;
11298
11299 if ((kIOPMAOTModeAddEventFlags & _aotMode) && (!flags || (flags == kIOPMWakeEventSource))) {
11300 flags |= kIOPMWakeEventAOTExit;
11301
11302 // Only allow lingering in AOT_STATE for the two wake reasons used for the wrist raise gesture.
11303 if (!strcmp("AOP.OutboxNotEmpty", reason) || !strcmp("spu_gesture", reason)) {
11304 flags &= ~kIOPMWakeEventAOTExit;
11305 }
11306 }
11307
11308 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
11309 // Publishing the WakeType is serialized by the PM work loop
11310 if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
11311 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
11312 (void *) _nextScheduledAlarmType.get());
11313 }
11314
11315 // Workaround for the missing wake HID event
11316 if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
11317 if (!strcmp("trackpadkeyboard", reason)) {
11318 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
11319 (void *) gIOPMWakeTypeUserKey.get());
11320 }
11321 }
11322 #endif
11323
11324 deviceName = device->copyName(gIOServicePlane);
11325 deviceRegId = OSNumber::withNumber(device->getRegistryEntryID(), 64);
11326 claimTime = OSNumber::withNumber(timestamp, 64);
11327 flagsData = OSData::withValue(flags);
11328 reasonString = OSString::withCString(reason);
11329 dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
11330 if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
11331 goto done;
11332 }
11333
11334 dict->setObject(gIONameKey, deviceName.get());
11335 dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
11336 dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
11337 dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
11338 dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
11339 if (details) {
11340 dict->setObject(kIOPMWakeEventDetailsKey, details);
11341 }
11342
11343 WAKEEVENT_LOCK();
11344 addWakeReason = _acceptSystemWakeEvents;
11345 if (_aotMode) {
11346 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
11347 }
11348 aotFlags = (kIOPMWakeEventAOTFlags & flags);
11349 aotFlags = (aotFlags & ~_aotPendingFlags);
11350 needAOTEvaluate = false;
11351 if (_aotNow && aotFlags) {
11352 if (kIOPMWakeEventAOTPossibleExit & flags) {
11353 _aotMetrics->possibleCount++;
11354 }
11355 if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
11356 _aotMetrics->confirmedPossibleCount++;
11357 }
11358 if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
11359 _aotMetrics->rejectedPossibleCount++;
11360 }
11361 if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
11362 _aotMetrics->expiredPossibleCount++;
11363 }
11364
11365 _aotPendingFlags |= aotFlags;
11366 addWakeReason = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
11367 needAOTEvaluate = _aotReadyToFullWake;
11368 }
11369 DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
11370 reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
11371 _aotNow, pmTracer->getTracePhase(), addWakeReason);
11372
11373 #if DEVELOPMENT || DEBUG
11374 if (addWakeReason) {
11375 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11376 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11377 "Report System Wake Event",
11378 "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
11379 reason,
11380 (int)flags,
11381 deviceName->getCStringNoCopy(),
11382 device->getRegistryEntryID()
11383 );
11384 }
11385 #endif /* DEVELOPMENT || DEBUG */
11386
11387 if (!gWakeReasonSysctlRegistered) {
11388 // Lazy registration until the platform driver stops registering
11389 // the same name.
11390 gWakeReasonSysctlRegistered = true;
11391 }
11392 if (addWakeReason) {
11393 _systemWakeEventsArray->setObject(dict.get());
11394 if (gWakeReasonString[0] != '\0') {
11395 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
11396 }
11397 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
11398 }
11399
11400 WAKEEVENT_UNLOCK();
11401 if (needAOTEvaluate) {
11402 // Call aotEvaluate() on PM work loop since it may call
11403 // aotExit() which accesses PM state.
11404 pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
11405 }
11406
11407 done:
11408 return;
11409 }
11410
11411 //******************************************************************************
11412 // claimSystemBootEvent
11413 //
11414 // For a driver to claim a device is the source/conduit of a system boot event.
11415 //******************************************************************************
11416
11417 void
11418 IOPMrootDomain::claimSystemBootEvent(
11419 IOService * device,
11420 IOOptionBits flags,
11421 const char * reason,
11422 __unused OSObject * details )
11423 {
11424 if (!device || !reason) {
11425 return;
11426 }
11427
11428 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11429 #if DEVELOPMENT || DEBUG
11430 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11431 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11432 "Report System Boot Device",
11433 "Reason: %s Flags: 0x%x Device: %s",
11434 reason,
11435 (int)flags,
11436 device->getName()
11437 );
11438 #endif /* DEVELOPMENT || DEBUG */
11439 WAKEEVENT_LOCK();
11440 if (!gBootReasonSysctlRegistered) {
11441 // Lazy sysctl registration after setting gBootReasonString
11442 strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
11443 os_atomic_store(&gBootReasonSysctlRegistered, true, release);
11444 }
11445 WAKEEVENT_UNLOCK();
11446 }
11447
11448 //******************************************************************************
11449 // claimSystemShutdownEvent
11450 //
11451 // For drivers to claim a system shutdown event on the ensuing boot.
11452 //******************************************************************************
11453
11454 void
11455 IOPMrootDomain::claimSystemShutdownEvent(
11456 IOService * device,
11457 IOOptionBits flags,
11458 const char * reason,
11459 OSObject * details )
11460 {
11461 if (!device || !reason) {
11462 return;
11463 }
11464
11465 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11466 #if DEVELOPMENT || DEBUG
11467 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11468 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11469 "Report System Shutdown Cause From Previous Boot",
11470 "Reason: %s Flags: 0x%x Device: %s",
11471 reason,
11472 (int)flags,
11473 device->getName()
11474 );
11475 #endif /* DEVELOPMENT || DEBUG */
11476 WAKEEVENT_LOCK();
11477 if (gShutdownReasonString[0] != '\0') {
11478 strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11479 }
11480 strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11481
11482 if (details) {
11483 OSDictionary *dict = OSDynamicCast(OSDictionary, details);
11484 if (dict) {
11485 OSSharedPtr<OSString> sharedKey = OSString::withCString(kIOPMRootDomainShutdownTime);
11486 if (sharedKey) {
11487 OSNumber *num = OSDynamicCast(OSNumber, dict->getObject(sharedKey.get()));
11488 if (num) {
11489 gShutdownTime = (uint64_t)(num->unsigned64BitValue());
11490 }
11491 }
11492 }
11493 }
11494
11495 gShutdownReasonSysctlRegistered = true;
11496 WAKEEVENT_UNLOCK();
11497 }
11498
11499 //******************************************************************************
11500 // requestRunMode
11501 //
11502 // For clients to request a LPW run mode. Only full wake is supported currently.
11503 //******************************************************************************
11504
11505 IOReturn
11506 IOPMrootDomain::requestRunMode(uint64_t runModeMask)
11507 {
11508 // We only support requesting full wake at the moment
11509 if (runModeMask == kIOPMRunModeFullWake) {
11510 pmPowerStateQueue->submitPowerEvent(kPowerEventRunModeRequest, NULL, runModeMask);
11511 return kIOReturnSuccess;
11512 }
11513 return kIOReturnUnsupported;
11514 }
11515
11516 IOReturn
11517 IOPMrootDomain::handleRequestRunMode(uint64_t runModeMask)
11518 {
11519 // TODO: Replace with run mode logic when implemented
11520 IOReturn ret = kIOReturnUnsupported;
11521
11522 // We only support requesting full wake at the moment
11523 if (runModeMask == kIOPMRunModeFullWake) {
11524 // A simple CPS should suffice for now
11525 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonEvaluatePolicy);
11526 ret = kIOReturnSuccess;
11527 }
11528
11529 DLOG("%s: mask %llx ret %x\n", __func__, runModeMask, ret);
11530 return ret;
11531 }
11532
11533 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11534
11535 // MARK: -
11536 // MARK: PMSettingHandle
11537
11538 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11539
11540 void
11541 PMSettingHandle::free( void )
11542 {
11543 if (pmso) {
11544 pmso->clientHandleFreed();
11545 pmso->release();
11546 pmso = NULL;
11547 }
11548
11549 OSObject::free();
11550 }
11551
11552 // MARK: -
11553 // MARK: PMSettingObject
11554
11555 #undef super
11556 #define super OSObject
11557 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11558
11559 /*
11560 * Static constructor/initializer for PMSettingObject
11561 */
11562 PMSettingObject *PMSettingObject::pmSettingObject(
11563 IOPMrootDomain * parent_arg,
11564 IOPMSettingControllerCallback handler_arg,
11565 OSObject * target_arg,
11566 uintptr_t refcon_arg,
11567 uint32_t supportedPowerSources,
11568 const OSSymbol * settings[],
11569 OSObject * *handle_obj)
11570 {
11571 uint32_t settingCount = 0;
11572 PMSettingObject *pmso = NULL;
11573 PMSettingHandle *pmsh = NULL;
11574
11575 if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11576 return NULL;
11577 }
11578
11579 // count OSSymbol entries in NULL terminated settings array
11580 while (settings[settingCount]) {
11581 settingCount++;
11582 }
11583 if (0 == settingCount) {
11584 return NULL;
11585 }
11586
11587 pmso = new PMSettingObject;
11588 if (!pmso || !pmso->init()) {
11589 goto fail;
11590 }
11591
11592 pmsh = new PMSettingHandle;
11593 if (!pmsh || !pmsh->init()) {
11594 goto fail;
11595 }
11596
11597 queue_init(&pmso->calloutQueue);
11598 pmso->parent = parent_arg;
11599 pmso->func = handler_arg;
11600 pmso->target = target_arg;
11601 pmso->refcon = refcon_arg;
11602 pmso->settingCount = settingCount;
11603
11604 pmso->retain(); // handle holds a retain on pmso
11605 pmsh->pmso = pmso;
11606 pmso->pmsh = pmsh;
11607
11608 pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11609 if (pmso->publishedFeatureID) {
11610 for (unsigned int i = 0; i < settingCount; i++) {
11611 // Since there is now at least one listener to this setting, publish
11612 // PM root domain support for it.
11613 parent_arg->publishPMSetting( settings[i],
11614 supportedPowerSources, &pmso->publishedFeatureID[i] );
11615 }
11616 }
11617
11618 *handle_obj = pmsh;
11619 return pmso;
11620
11621 fail:
11622 if (pmso) {
11623 pmso->release();
11624 }
11625 if (pmsh) {
11626 pmsh->release();
11627 }
11628 return NULL;
11629 }
11630
11631 void
11632 PMSettingObject::free( void )
11633 {
11634 if (publishedFeatureID) {
11635 for (const auto& featureID : publishedFeatureID) {
11636 if (featureID) {
11637 parent->removePublishedFeature( featureID );
11638 }
11639 }
11640
11641 publishedFeatureID = {};
11642 }
11643
11644 super::free();
11645 }
11646
11647 IOReturn
11648 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11649 {
11650 return (*func)(target, type, object, refcon);
11651 }
11652
11653 void
11654 PMSettingObject::clientHandleFreed( void )
11655 {
11656 parent->deregisterPMSettingObject(this);
11657 }
11658
11659 // MARK: -
11660 // MARK: PMAssertionsTracker
11661
11662 //*********************************************************************************
11663 //*********************************************************************************
11664 //*********************************************************************************
11665 // class PMAssertionsTracker Implementation
11666
11667 #define kAssertUniqueIDStart 500
11668
11669 PMAssertionsTracker *
11670 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11671 {
11672 PMAssertionsTracker *me;
11673
11674 me = new PMAssertionsTracker;
11675 if (!me || !me->init()) {
11676 if (me) {
11677 me->release();
11678 }
11679 return NULL;
11680 }
11681
11682 me->owner = rootDomain;
11683 me->issuingUniqueID = kAssertUniqueIDStart;
11684 me->assertionsArray = OSArray::withCapacity(5);
11685 me->assertionsKernel = 0;
11686 me->assertionsUser = 0;
11687 me->assertionsCombined = 0;
11688 me->assertionsArrayLock = IOLockAlloc();
11689 me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11690
11691 assert(me->assertionsArray);
11692 assert(me->assertionsArrayLock);
11693
11694 return me;
11695 }
11696
11697 /* tabulate
11698 * - Update assertionsKernel to reflect the state of all
11699 * assertions in the kernel.
11700 * - Update assertionsCombined to reflect both kernel & user space.
11701 */
11702 void
11703 PMAssertionsTracker::tabulate(void)
11704 {
11705 int i;
11706 int count;
11707 const PMAssertStruct *_a = nullptr;
11708 OSValueObject<PMAssertStruct> *_d = nullptr;
11709
11710 IOPMDriverAssertionType oldKernel = assertionsKernel;
11711 IOPMDriverAssertionType oldCombined = assertionsCombined;
11712
11713 ASSERT_GATED();
11714
11715 assertionsKernel = 0;
11716 assertionsCombined = 0;
11717
11718 if (!assertionsArray) {
11719 return;
11720 }
11721
11722 if ((count = assertionsArray->getCount())) {
11723 for (i = 0; i < count; i++) {
11724 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11725 if (_d) {
11726 _a = _d->getBytesNoCopy();
11727 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11728 assertionsKernel |= _a->assertionBits;
11729 }
11730 }
11731 }
11732 }
11733
11734 tabulateProducerCount++;
11735 assertionsCombined = assertionsKernel | assertionsUser;
11736
11737 if ((assertionsKernel != oldKernel) ||
11738 (assertionsCombined != oldCombined)) {
11739 owner->evaluateAssertions(assertionsCombined, oldCombined);
11740 }
11741 }
11742
11743 void
11744 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11745 {
11746 AbsoluteTime now;
11747 uint64_t nsec;
11748
11749 if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11750 (assertStruct->assertCPUStartTime == 0)) {
11751 return;
11752 }
11753
11754 now = mach_absolute_time();
11755 SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11756 absolutetime_to_nanoseconds(now, &nsec);
11757 assertStruct->assertCPUDuration += nsec;
11758 assertStruct->assertCPUStartTime = 0;
11759
11760 if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11761 maxAssertCPUDuration = assertStruct->assertCPUDuration;
11762 maxAssertCPUEntryId = assertStruct->registryEntryID;
11763 }
11764 }
11765
11766 void
11767 PMAssertionsTracker::reportCPUBitAccounting( void )
11768 {
11769 const PMAssertStruct *_a = nullptr;
11770 OSValueObject<PMAssertStruct> *_d = nullptr;
11771 int i, count;
11772 AbsoluteTime now;
11773 uint64_t nsec;
11774
11775 ASSERT_GATED();
11776
11777 // Account for drivers that are still holding the CPU assertion
11778 if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11779 now = mach_absolute_time();
11780 if ((count = assertionsArray->getCount())) {
11781 for (i = 0; i < count; i++) {
11782 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11783 if (_d) {
11784 _a = _d->getBytesNoCopy();
11785 if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11786 (_a->level == kIOPMDriverAssertionLevelOn) &&
11787 (_a->assertCPUStartTime != 0)) {
11788 // Don't modify PMAssertStruct, leave that
11789 // for updateCPUBitAccounting()
11790 SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11791 absolutetime_to_nanoseconds(now, &nsec);
11792 nsec += _a->assertCPUDuration;
11793 if (nsec > maxAssertCPUDuration) {
11794 maxAssertCPUDuration = nsec;
11795 maxAssertCPUEntryId = _a->registryEntryID;
11796 }
11797 }
11798 }
11799 }
11800 }
11801 }
11802
11803 if (maxAssertCPUDuration) {
11804 DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11805 (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11806 }
11807
11808 maxAssertCPUDuration = 0;
11809 maxAssertCPUEntryId = 0;
11810 }
11811
11812 void
11813 PMAssertionsTracker::publishProperties( void )
11814 {
11815 OSSharedPtr<OSArray> assertionsSummary;
11816
11817 if (tabulateConsumerCount != tabulateProducerCount) {
11818 IOLockLock(assertionsArrayLock);
11819
11820 tabulateConsumerCount = tabulateProducerCount;
11821
11822 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11823 */
11824 assertionsSummary = copyAssertionsArray();
11825 if (assertionsSummary) {
11826 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11827 } else {
11828 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11829 }
11830
11831 /* Publish the IOPMrootDomain property "DriverPMAssertions"
11832 */
11833 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11834
11835 IOLockUnlock(assertionsArrayLock);
11836 }
11837 }
11838
11839 PMAssertStruct *
11840 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11841 {
11842 PMAssertStruct *_a = NULL;
11843 OSValueObject<PMAssertStruct> *_d = nullptr;
11844 int found = -1;
11845 int count = 0;
11846 int i = 0;
11847
11848 if (assertionsArray
11849 && (count = assertionsArray->getCount())) {
11850 for (i = 0; i < count; i++) {
11851 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11852 if (_d) {
11853 _a = _d->getMutableBytesNoCopy();
11854 if (_a && (_id == _a->id)) {
11855 found = i;
11856 break;
11857 }
11858 }
11859 }
11860 }
11861
11862 if (-1 == found) {
11863 return NULL;
11864 } else {
11865 if (index) {
11866 *index = found;
11867 }
11868 return _a;
11869 }
11870 }
11871
11872 /* PMAssertionsTracker::handleCreateAssertion
11873 * Perform assertion work on the PM workloop. Do not call directly.
11874 */
11875 IOReturn
11876 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11877 {
11878 PMAssertStruct *assertStruct = nullptr;
11879
11880 ASSERT_GATED();
11881
11882 if (newAssertion) {
11883 IOLockLock(assertionsArrayLock);
11884 assertStruct = newAssertion->getMutableBytesNoCopy();
11885 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11886 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11887 assertStruct->assertCPUStartTime = mach_absolute_time();
11888 }
11889 assertionsArray->setObject(newAssertion);
11890 IOLockUnlock(assertionsArrayLock);
11891 newAssertion->release();
11892
11893 tabulate();
11894 }
11895 return kIOReturnSuccess;
11896 }
11897
11898 /* PMAssertionsTracker::createAssertion
11899 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11900 * appropiate.
11901 */
11902 IOReturn
11903 PMAssertionsTracker::createAssertion(
11904 IOPMDriverAssertionType which,
11905 IOPMDriverAssertionLevel level,
11906 IOService *serviceID,
11907 const char *whoItIs,
11908 IOPMDriverAssertionID *outID)
11909 {
11910 OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11911 PMAssertStruct track;
11912
11913 // Warning: trillions and trillions of created assertions may overflow the unique ID.
11914 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11915 track.level = level;
11916 track.assertionBits = which;
11917
11918 // NB: ownerString is explicitly managed by PMAssertStruct
11919 // it will be released in `handleReleaseAssertion' below
11920 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11921 track.ownerService = serviceID;
11922 track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11923 track.modifiedTime = 0;
11924 pmEventTimeStamp(&track.createdTime);
11925 track.assertCPUStartTime = 0;
11926 track.assertCPUDuration = 0;
11927
11928 dataStore = OSValueObjectWithValue(track);
11929 if (!dataStore) {
11930 if (track.ownerString) {
11931 track.ownerString->release();
11932 track.ownerString = NULL;
11933 }
11934 return kIOReturnNoMemory;
11935 }
11936
11937 *outID = track.id;
11938
11939 if (owner && owner->pmPowerStateQueue) {
11940 // queue action is responsible for releasing dataStore
11941 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11942 }
11943
11944 return kIOReturnSuccess;
11945 }
11946
11947 /* PMAssertionsTracker::handleReleaseAssertion
11948 * Runs in PM workloop. Do not call directly.
11949 */
11950 IOReturn
11951 PMAssertionsTracker::handleReleaseAssertion(
11952 IOPMDriverAssertionID _id)
11953 {
11954 ASSERT_GATED();
11955
11956 int index;
11957 PMAssertStruct *assertStruct = detailsForID(_id, &index);
11958
11959 if (!assertStruct) {
11960 return kIOReturnNotFound;
11961 }
11962
11963 IOLockLock(assertionsArrayLock);
11964
11965 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11966 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11967 updateCPUBitAccounting(assertStruct);
11968 }
11969
11970 if (assertStruct->ownerString) {
11971 assertStruct->ownerString->release();
11972 assertStruct->ownerString = NULL;
11973 }
11974
11975 assertionsArray->removeObject(index);
11976 IOLockUnlock(assertionsArrayLock);
11977
11978 tabulate();
11979 return kIOReturnSuccess;
11980 }
11981
11982 /* PMAssertionsTracker::releaseAssertion
11983 * Releases an assertion and affects system behavior if appropiate.
11984 * Actual work happens on PM workloop.
11985 */
11986 IOReturn
11987 PMAssertionsTracker::releaseAssertion(
11988 IOPMDriverAssertionID _id)
11989 {
11990 if (owner && owner->pmPowerStateQueue) {
11991 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11992 }
11993 return kIOReturnSuccess;
11994 }
11995
11996 /* PMAssertionsTracker::handleSetAssertionLevel
11997 * Runs in PM workloop. Do not call directly.
11998 */
11999 IOReturn
12000 PMAssertionsTracker::handleSetAssertionLevel(
12001 IOPMDriverAssertionID _id,
12002 IOPMDriverAssertionLevel _level)
12003 {
12004 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
12005
12006 ASSERT_GATED();
12007
12008 if (!assertStruct) {
12009 return kIOReturnNotFound;
12010 }
12011
12012 IOLockLock(assertionsArrayLock);
12013 pmEventTimeStamp(&assertStruct->modifiedTime);
12014 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
12015 (assertStruct->level != _level)) {
12016 if (_level == kIOPMDriverAssertionLevelOn) {
12017 assertStruct->assertCPUStartTime = mach_absolute_time();
12018 } else {
12019 updateCPUBitAccounting(assertStruct);
12020 }
12021 }
12022 assertStruct->level = _level;
12023 IOLockUnlock(assertionsArrayLock);
12024
12025 tabulate();
12026 return kIOReturnSuccess;
12027 }
12028
12029 /* PMAssertionsTracker::setAssertionLevel
12030 */
12031 IOReturn
12032 PMAssertionsTracker::setAssertionLevel(
12033 IOPMDriverAssertionID _id,
12034 IOPMDriverAssertionLevel _level)
12035 {
12036 if (owner && owner->pmPowerStateQueue) {
12037 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
12038 (void *)(uintptr_t)_level, _id);
12039 }
12040
12041 return kIOReturnSuccess;
12042 }
12043
12044 IOReturn
12045 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
12046 {
12047 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
12048
12049 ASSERT_GATED();
12050
12051 if (new_user_levels != assertionsUser) {
12052 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
12053 assertionsUser = new_user_levels;
12054 }
12055
12056 tabulate();
12057 return kIOReturnSuccess;
12058 }
12059
12060 IOReturn
12061 PMAssertionsTracker::setUserAssertionLevels(
12062 IOPMDriverAssertionType new_user_levels)
12063 {
12064 if (gIOPMWorkLoop) {
12065 gIOPMWorkLoop->runAction(
12066 OSMemberFunctionCast(
12067 IOWorkLoop::Action,
12068 this,
12069 &PMAssertionsTracker::handleSetUserAssertionLevels),
12070 this,
12071 (void *) &new_user_levels, NULL, NULL, NULL);
12072 }
12073
12074 return kIOReturnSuccess;
12075 }
12076
12077
12078 OSSharedPtr<OSArray>
12079 PMAssertionsTracker::copyAssertionsArray(void)
12080 {
12081 int count;
12082 int i;
12083 OSSharedPtr<OSArray> outArray = NULL;
12084
12085 if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
12086 goto exit;
12087 }
12088 outArray = OSArray::withCapacity(count);
12089 if (!outArray) {
12090 goto exit;
12091 }
12092
12093 for (i = 0; i < count; i++) {
12094 const PMAssertStruct *_a = nullptr;
12095 OSValueObject<PMAssertStruct> *_d = nullptr;
12096 OSSharedPtr<OSDictionary> details;
12097
12098 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
12099 if (_d && (_a = _d->getBytesNoCopy())) {
12100 OSSharedPtr<OSNumber> _n;
12101
12102 details = OSDictionary::withCapacity(7);
12103 if (!details) {
12104 continue;
12105 }
12106
12107 outArray->setObject(details.get());
12108
12109 _n = OSNumber::withNumber(_a->id, 64);
12110 if (_n) {
12111 details->setObject(kIOPMDriverAssertionIDKey, _n.get());
12112 }
12113 _n = OSNumber::withNumber(_a->createdTime, 64);
12114 if (_n) {
12115 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
12116 }
12117 _n = OSNumber::withNumber(_a->modifiedTime, 64);
12118 if (_n) {
12119 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
12120 }
12121 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
12122 if (_n) {
12123 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
12124 }
12125 _n = OSNumber::withNumber(_a->level, 64);
12126 if (_n) {
12127 details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
12128 }
12129 _n = OSNumber::withNumber(_a->assertionBits, 64);
12130 if (_n) {
12131 details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
12132 }
12133
12134 if (_a->ownerString) {
12135 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
12136 }
12137 }
12138 }
12139
12140 exit:
12141 return os::move(outArray);
12142 }
12143
12144 IOPMDriverAssertionType
12145 PMAssertionsTracker::getActivatedAssertions(void)
12146 {
12147 return assertionsCombined;
12148 }
12149
12150 IOPMDriverAssertionLevel
12151 PMAssertionsTracker::getAssertionLevel(
12152 IOPMDriverAssertionType type)
12153 {
12154 // FIXME: unused and also wrong
12155 if (type && ((type & assertionsKernel) == assertionsKernel)) {
12156 return kIOPMDriverAssertionLevelOn;
12157 } else {
12158 return kIOPMDriverAssertionLevelOff;
12159 }
12160 }
12161
12162 //*********************************************************************************
12163 //*********************************************************************************
12164 //*********************************************************************************
12165
12166
12167 static void
12168 pmEventTimeStamp(uint64_t *recordTS)
12169 {
12170 clock_sec_t tsec;
12171 clock_usec_t tusec;
12172
12173 if (!recordTS) {
12174 return;
12175 }
12176
12177 // We assume tsec fits into 32 bits; 32 bits holds enough
12178 // seconds for 136 years since the epoch in 1970.
12179 clock_get_calendar_microtime(&tsec, &tusec);
12180
12181
12182 // Pack the sec & microsec calendar time into a uint64_t, for fun.
12183 *recordTS = 0;
12184 *recordTS |= (uint32_t)tusec;
12185 *recordTS |= ((uint64_t)tsec << 32);
12186
12187 return;
12188 }
12189
12190 // MARK: -
12191 // MARK: IORootParent
12192
12193 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12194
12195 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
12196
12197 // The reason that root domain needs a root parent is to facilitate demand
12198 // sleep, since a power change from the root parent cannot be vetoed.
12199 //
12200 // The above statement is no longer true since root domain now performs
12201 // demand sleep using overrides. But root parent remains to avoid changing
12202 // the power tree stacking. Root parent is parked at the max power state.
12203
12204
12205 static IOPMPowerState patriarchPowerStates[2] =
12206 {
12207 {.version = kIOPMPowerStateVersion1, .outputPowerCharacter = ON_POWER },
12208 {.version = kIOPMPowerStateVersion1, .outputPowerCharacter = ON_POWER }
12209 };
12210
12211 void
12212 IORootParent::initialize( void )
12213 {
12214
12215 gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
12216 gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
12217 gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
12218 gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
12219 gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
12220 gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
12221 gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
12222 gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
12223 gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
12224 gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
12225 gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
12226 gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
12227 gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
12228 gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
12229 gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
12230 gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
12231 gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
12232 gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
12233 gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
12234 gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
12235 gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
12236 gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
12237 gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
12238 gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
12239 gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
12240 gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
12241 gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
12242 gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
12243 gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
12244 gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
12245 gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
12246 gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
12247 gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
12248 gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
12249 gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
12250 gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
12251 gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
12252 gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
12253 gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
12254 gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
12255 gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
12256 gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
12257 gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
12258 gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
12259 }
12260
12261 bool
12262 IORootParent::start( IOService * nub )
12263 {
12264 IOService::start(nub);
12265 attachToParent( getRegistryRoot(), gIOPowerPlane );
12266 PMinit();
12267 registerPowerDriver(this, patriarchPowerStates, 2);
12268 makeUsable();
12269 return true;
12270 }
12271
12272 void
12273 IORootParent::shutDownSystem( void )
12274 {
12275 }
12276
12277 void
12278 IORootParent::restartSystem( void )
12279 {
12280 }
12281
12282 void
12283 IORootParent::sleepSystem( void )
12284 {
12285 }
12286
12287 void
12288 IORootParent::dozeSystem( void )
12289 {
12290 }
12291
12292 void
12293 IORootParent::sleepToDoze( void )
12294 {
12295 }
12296
12297 void
12298 IORootParent::wakeSystem( void )
12299 {
12300 }
12301
12302 OSSharedPtr<OSObject>
12303 IORootParent::copyProperty( const char * aKey) const
12304 {
12305 return IOService::copyProperty(aKey);
12306 }
12307
12308 uint32_t
12309 IOPMrootDomain::getWatchdogTimeout()
12310 {
12311 if (gSwdSleepWakeTimeout) {
12312 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
12313 }
12314 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
12315 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
12316 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
12317 } else {
12318 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
12319 }
12320 }
12321
12322
12323 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
12324 IOReturn
12325 IOPMrootDomain::restartWithStackshot()
12326 {
12327 takeStackshot(true);
12328
12329 return kIOReturnSuccess;
12330 }
12331
12332 void
12333 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
12334 {
12335 takeStackshot(wdogTrigger);
12336 }
12337
12338 void
12339 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
12340 {
12341 switch (tracePhase) {
12342 case kIOPMTracePointSleepStarted:
12343 *phaseString = "kIOPMTracePointSleepStarted";
12344 *description = "starting sleep";
12345 break;
12346
12347 case kIOPMTracePointSleepApplications:
12348 *phaseString = "kIOPMTracePointSleepApplications";
12349 *description = "notifying applications";
12350 break;
12351
12352 case kIOPMTracePointSleepPriorityClients:
12353 *phaseString = "kIOPMTracePointSleepPriorityClients";
12354 *description = "notifying clients about upcoming system capability changes";
12355 break;
12356
12357 case kIOPMTracePointSleepWillChangeInterests:
12358 *phaseString = "kIOPMTracePointSleepWillChangeInterests";
12359 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
12360 break;
12361
12362 case kIOPMTracePointSleepPowerPlaneDrivers:
12363 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
12364 *description = "calling power state change callbacks";
12365 break;
12366
12367 case kIOPMTracePointSleepDidChangeInterests:
12368 *phaseString = "kIOPMTracePointSleepDidChangeInterests";
12369 *description = "calling rootDomain's clients about rootDomain's state changes";
12370 break;
12371
12372 case kIOPMTracePointSleepCapabilityClients:
12373 *phaseString = "kIOPMTracePointSleepCapabilityClients";
12374 *description = "notifying clients about current system capabilities";
12375 break;
12376
12377 case kIOPMTracePointSleepPlatformActions:
12378 *phaseString = "kIOPMTracePointSleepPlatformActions";
12379 *description = "calling Quiesce/Sleep action callbacks";
12380 break;
12381
12382 case kIOPMTracePointSleepCPUs:
12383 {
12384 *phaseString = "kIOPMTracePointSleepCPUs";
12385 #if defined(__i386__) || defined(__x86_64__)
12386 /*
12387 * We cannot use the getCPUNumber() method to get the cpu number, since
12388 * that cpu number is unrelated to the cpu number we need (we need the cpu
12389 * number as enumerated by the scheduler, NOT the CPU number enumerated
12390 * by ACPIPlatform as the CPUs are enumerated in MADT order).
12391 * Instead, pass the Mach processor pointer associated with the current
12392 * shutdown target so its associated cpu_id can be used in
12393 * processor_to_datastring.
12394 */
12395 if (currentShutdownTarget != NULL &&
12396 currentShutdownTarget->getMachProcessor() != NULL) {
12397 const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
12398 currentShutdownTarget->getMachProcessor());
12399 *description = sbuf;
12400 } else {
12401 *description = "halting all non-boot CPUs";
12402 }
12403 #else
12404 *description = "halting all non-boot CPUs";
12405 #endif
12406 break;
12407 }
12408 case kIOPMTracePointSleepPlatformDriver:
12409 *phaseString = "kIOPMTracePointSleepPlatformDriver";
12410 *description = "executing platform specific code";
12411 break;
12412
12413 case kIOPMTracePointHibernate:
12414 *phaseString = "kIOPMTracePointHibernate";
12415 *description = "writing the hibernation image";
12416 break;
12417
12418 case kIOPMTracePointSystemSleep:
12419 *phaseString = "kIOPMTracePointSystemSleep";
12420 *description = "in EFI/Bootrom after last point of entry to sleep";
12421 break;
12422
12423 case kIOPMTracePointWakePlatformDriver:
12424 *phaseString = "kIOPMTracePointWakePlatformDriver";
12425 *description = "executing platform specific code";
12426 break;
12427
12428
12429 case kIOPMTracePointWakePlatformActions:
12430 *phaseString = "kIOPMTracePointWakePlatformActions";
12431 *description = "calling Wake action callbacks";
12432 break;
12433
12434 case kIOPMTracePointWakeCPUs:
12435 *phaseString = "kIOPMTracePointWakeCPUs";
12436 *description = "starting non-boot CPUs";
12437 break;
12438
12439 case kIOPMTracePointWakeWillPowerOnClients:
12440 *phaseString = "kIOPMTracePointWakeWillPowerOnClients";
12441 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
12442 break;
12443
12444 case kIOPMTracePointWakeWillChangeInterests:
12445 *phaseString = "kIOPMTracePointWakeWillChangeInterests";
12446 *description = "calling rootDomain's clients about upcoming rootDomain's state changes";
12447 break;
12448
12449 case kIOPMTracePointWakeDidChangeInterests:
12450 *phaseString = "kIOPMTracePointWakeDidChangeInterests";
12451 *description = "calling rootDomain's clients about completed rootDomain's state changes";
12452 break;
12453
12454 case kIOPMTracePointWakePowerPlaneDrivers:
12455 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
12456 *description = "calling power state change callbacks";
12457 break;
12458
12459 case kIOPMTracePointWakeCapabilityClients:
12460 *phaseString = "kIOPMTracePointWakeCapabilityClients";
12461 *description = "informing clients about current system capabilities";
12462 break;
12463
12464 case kIOPMTracePointWakeApplications:
12465 *phaseString = "kIOPMTracePointWakeApplications";
12466 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
12467 break;
12468
12469 case kIOPMTracePointDarkWakeEntry:
12470 *phaseString = "kIOPMTracePointDarkWakeEntry";
12471 *description = "entering darkwake on way to sleep";
12472 break;
12473
12474 case kIOPMTracePointDarkWakeExit:
12475 *phaseString = "kIOPMTracePointDarkWakeExit";
12476 *description = "entering fullwake from darkwake";
12477 break;
12478
12479 default:
12480 *phaseString = NULL;
12481 *description = NULL;
12482 }
12483 }
12484
12485 void
12486 IOPMrootDomain::saveFailureData2File()
12487 {
12488 unsigned int len = 0;
12489 char failureStr[512];
12490 errno_t error;
12491 char *outbuf;
12492 OSNumber *statusCode;
12493 uint64_t pmStatusCode = 0;
12494 uint32_t phaseData = 0;
12495 uint32_t phaseDetail = 0;
12496 bool efiFailure = false;
12497
12498 OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
12499 statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
12500 if (statusCode) {
12501 pmStatusCode = statusCode->unsigned64BitValue();
12502 phaseData = pmStatusCode & 0xFFFFFFFF;
12503 phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
12504 if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
12505 LOG("Sleep Wake failure in EFI\n");
12506 efiFailure = true;
12507 failureStr[0] = 0;
12508 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);
12509 len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12510 }
12511 }
12512
12513 if (!efiFailure) {
12514 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12515 swd_flags |= SWD_BOOT_BY_SW_WDOG;
12516 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12517 // dump panic will handle saving nvram data
12518 return;
12519 }
12520
12521 /* Keeping this around for capturing data during power
12522 * button press */
12523
12524 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12525 DLOG("No sleep wake failure string\n");
12526 return;
12527 }
12528 if (len == 0) {
12529 DLOG("Ignoring zero byte SleepWake failure string\n");
12530 goto exit;
12531 }
12532
12533 // if PMStatus code is zero, delete stackshot and return
12534 if (statusCode) {
12535 if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12536 // there was no sleep wake failure
12537 // this can happen if delete stackshot was called
12538 // before take stackshot completed. Let us delete any
12539 // sleep wake failure data in nvram
12540 DLOG("Deleting stackshot on successful wake\n");
12541 deleteStackshot();
12542 return;
12543 }
12544 }
12545
12546 if (len > sizeof(failureStr)) {
12547 len = sizeof(failureStr);
12548 }
12549 failureStr[0] = 0;
12550 PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12551 }
12552 if (failureStr[0] != 0) {
12553 error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12554 if (error) {
12555 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12556 } else {
12557 DLOG("Saved SleepWake failure string to file.\n");
12558 }
12559 }
12560
12561 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12562 goto exit;
12563 }
12564
12565 if (swd_buffer) {
12566 unsigned int len = 0;
12567 errno_t error;
12568 char nvram_var_name_buffer[20];
12569 unsigned int concat_len = 0;
12570 swd_hdr *hdr = NULL;
12571
12572
12573 hdr = (swd_hdr *)swd_buffer;
12574 outbuf = (char *)hdr + hdr->spindump_offset;
12575 OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12576
12577 for (int i = 0; i < 8; i++) {
12578 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12579 if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12580 LOG("No SleepWake blob to read beyond chunk %d\n", i);
12581 break;
12582 }
12583 if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12584 PERemoveNVRAMProperty(nvram_var_name_buffer);
12585 LOG("Could not read the property :-(\n");
12586 break;
12587 }
12588 PERemoveNVRAMProperty(nvram_var_name_buffer);
12589 concat_len += len;
12590 }
12591 LOG("Concatenated length for the SWD blob %d\n", concat_len);
12592
12593 if (concat_len) {
12594 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12595 if (error) {
12596 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12597 } else {
12598 LOG("Saved SleepWake zipped data to file.\n");
12599 }
12600 } else {
12601 // There is a sleep wake failure string but no stackshot
12602 // Write a placeholder stacks file so that swd runs
12603 snprintf(outbuf, 20, "%s", "No stackshot data\n");
12604 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12605 if (error) {
12606 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12607 } else {
12608 LOG("Saved SleepWake zipped data to file.\n");
12609 }
12610 }
12611 } else {
12612 LOG("No buffer allocated to save failure stackshot\n");
12613 }
12614
12615
12616 gRootDomain->swd_lock = 0;
12617 exit:
12618 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12619 return;
12620 }
12621
12622
12623 void
12624 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12625 {
12626 OSSharedPtr<IORegistryIterator> iter;
12627 OSSharedPtr<const OSSymbol> kextName = NULL;
12628 IORegistryEntry * entry;
12629 IOService * node;
12630 bool nodeFound = false;
12631
12632 const void * callMethod = NULL;
12633 const char * objectName = NULL;
12634 const char * phaseString = NULL;
12635 const char * phaseDescription = NULL;
12636 uint64_t delta;
12637
12638 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12639 uint32_t tracePhase = pmTracer->getTracePhase();
12640
12641 *thread = NULL;
12642
12643 delta = get_watchdog_elapsed_time();
12644 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12645 snprintf(failureStr, strLen, "Sleep transition timed out after %qd seconds", delta);
12646 } else {
12647 snprintf(failureStr, strLen, "Wake transition timed out after %qd seconds", delta);
12648 }
12649 tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12650
12651 if (notifierThread) {
12652 if (notifier && (notifier->identifier)) {
12653 objectName = notifier->identifier->getCStringNoCopy();
12654 }
12655 *thread = notifierThread;
12656 } else {
12657 iter = IORegistryIterator::iterateOver(
12658 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12659
12660 if (iter) {
12661 while ((entry = iter->getNextObject())) {
12662 node = OSDynamicCast(IOService, entry);
12663 if (!node) {
12664 continue;
12665 }
12666 if (OSDynamicCast(IOPowerConnection, node)) {
12667 continue;
12668 }
12669
12670 if (node->getBlockingDriverCall(thread, &callMethod)) {
12671 nodeFound = true;
12672 break;
12673 }
12674 }
12675 }
12676 if (nodeFound) {
12677 kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12678 if (kextName) {
12679 objectName = kextName->getCStringNoCopy();
12680 }
12681 }
12682 }
12683 if (phaseDescription) {
12684 strlcat(failureStr, " while ", strLen);
12685 strlcat(failureStr, phaseDescription, strLen);
12686 strlcat(failureStr, ".", strLen);
12687 }
12688 if (objectName) {
12689 strlcat(failureStr, " Suspected bundle: ", strLen);
12690 strlcat(failureStr, objectName, strLen);
12691 strlcat(failureStr, ".", strLen);
12692 }
12693 if (*thread) {
12694 char threadName[40];
12695 snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12696 strlcat(failureStr, threadName, strLen);
12697 }
12698
12699 DLOG("%s\n", failureStr);
12700 }
12701
12702 struct swd_stackshot_compressed_data {
12703 z_output_func zoutput;
12704 size_t zipped;
12705 uint64_t totalbytes;
12706 uint64_t lastpercent;
12707 IOReturn error;
12708 unsigned outremain;
12709 unsigned outlen;
12710 unsigned writes;
12711 Bytef * outbuf;
12712 };
12713 struct swd_stackshot_compressed_data swd_zip_var = { };
12714
12715 static void *
12716 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12717 {
12718 void *result;
12719 LOG("Alloc in zipping %d items of size %d\n", items, size);
12720
12721 result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12722 swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12723 LOG("Offset %zu\n", swd_zs_zoffset);
12724 return result;
12725 }
12726
12727 static int
12728 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12729 {
12730 unsigned len;
12731
12732 len = strm->avail_in;
12733
12734 if (len > size) {
12735 len = size;
12736 }
12737 if (len == 0) {
12738 return 0;
12739 }
12740
12741 if (strm->next_in != (Bytef *) strm) {
12742 memcpy(buf, strm->next_in, len);
12743 } else {
12744 bzero(buf, len);
12745 }
12746
12747 strm->adler = z_crc32(strm->adler, buf, len);
12748
12749 strm->avail_in -= len;
12750 strm->next_in += len;
12751 strm->total_in += len;
12752
12753 return (int)len;
12754 }
12755
12756 static int
12757 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12758 {
12759 unsigned int i = 0;
12760 // if outlen > max size don't add to the buffer
12761 assert(buf != NULL);
12762 if (strm && buf) {
12763 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12764 LOG("No space to GZIP... not writing to NVRAM\n");
12765 return len;
12766 }
12767 }
12768 for (i = 0; i < len; i++) {
12769 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12770 }
12771 swd_zip_var.outlen += len;
12772 return len;
12773 }
12774
12775 static void
12776 swd_zs_free(void * __unused ref, void * __unused ptr)
12777 {
12778 }
12779
12780 static int
12781 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12782 {
12783 int wbits = 12;
12784 int memlevel = 3;
12785
12786 if (((unsigned int) numBytes) != numBytes) {
12787 return 0;
12788 }
12789
12790 if (!swd_zs.zalloc) {
12791 swd_zs.zalloc = swd_zs_alloc;
12792 swd_zs.zfree = swd_zs_free;
12793 if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12794 // allocation failed
12795 bzero(&swd_zs, sizeof(swd_zs));
12796 // swd_zs_zoffset = 0;
12797 } else {
12798 LOG("PMRD inited the zlib allocation routines\n");
12799 }
12800 }
12801
12802 swd_zip_var.zipped = 0;
12803 swd_zip_var.totalbytes = 0; // should this be the max that we have?
12804 swd_zip_var.lastpercent = 0;
12805 swd_zip_var.error = kIOReturnSuccess;
12806 swd_zip_var.outremain = 0;
12807 swd_zip_var.outlen = 0;
12808 swd_zip_var.writes = 0;
12809 swd_zip_var.outbuf = (Bytef *)outPtr;
12810
12811 swd_zip_var.totalbytes = numBytes;
12812
12813 swd_zs.avail_in = 0;
12814 swd_zs.next_in = NULL;
12815 swd_zs.avail_out = 0;
12816 swd_zs.next_out = NULL;
12817
12818 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12819
12820 z_stream *zs;
12821 int zr;
12822 zs = &swd_zs;
12823
12824 while (swd_zip_var.error >= 0) {
12825 if (!zs->avail_in) {
12826 zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12827 zs->avail_in = (unsigned int) numBytes;
12828 }
12829 if (!zs->avail_out) {
12830 zs->next_out = (Bytef *)zs;
12831 zs->avail_out = UINT32_MAX;
12832 }
12833 zr = deflate(zs, Z_NO_FLUSH);
12834 if (Z_STREAM_END == zr) {
12835 break;
12836 }
12837 if (zr != Z_OK) {
12838 LOG("ZERR %d\n", zr);
12839 swd_zip_var.error = zr;
12840 } else {
12841 if (zs->total_in == numBytes) {
12842 break;
12843 }
12844 }
12845 }
12846
12847 //now flush the stream
12848 while (swd_zip_var.error >= 0) {
12849 if (!zs->avail_out) {
12850 zs->next_out = (Bytef *)zs;
12851 zs->avail_out = UINT32_MAX;
12852 }
12853 zr = deflate(zs, Z_FINISH);
12854 if (Z_STREAM_END == zr) {
12855 break;
12856 }
12857 if (zr != Z_OK) {
12858 LOG("ZERR %d\n", zr);
12859 swd_zip_var.error = zr;
12860 } else {
12861 if (zs->total_in == numBytes) {
12862 LOG("Total output size %d\n", swd_zip_var.outlen);
12863 break;
12864 }
12865 }
12866 }
12867
12868 return swd_zip_var.outlen;
12869 }
12870
12871 void
12872 IOPMrootDomain::deleteStackshot()
12873 {
12874 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12875 // takeStackshot hasn't completed
12876 return;
12877 }
12878 LOG("Deleting any sleepwake failure data in nvram\n");
12879
12880 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12881 char nvram_var_name_buf[20];
12882 for (int i = 0; i < 8; i++) {
12883 snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12884 if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12885 LOG("Removing %s returned false\n", nvram_var_name_buf);
12886 }
12887 }
12888 // force NVRAM sync
12889 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12890 DLOG("Failed to force nvram sync\n");
12891 }
12892 gRootDomain->swd_lock = 0;
12893 }
12894
12895 void
12896 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12897 {
12898 swd_hdr * hdr = NULL;
12899 int cnt = 0;
12900 int max_cnt;
12901 pid_t pid = 0;
12902 kern_return_t kr = KERN_SUCCESS;
12903 uint64_t flags;
12904
12905 char * dstAddr;
12906 uint32_t size;
12907 uint32_t bytesRemaining;
12908 unsigned bytesWritten = 0;
12909
12910 char failureStr[512];
12911 thread_t thread = NULL;
12912 const char * swfPanic = "swfPanic";
12913
12914 uint32_t bufSize;
12915 int success = 0;
12916
12917 #if defined(__i386__) || defined(__x86_64__)
12918 const bool concise = false;
12919 #else
12920 const bool concise = true;
12921 #endif
12922
12923 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12924 return;
12925 }
12926
12927 failureStr[0] = 0;
12928 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12929 return;
12930 }
12931
12932 if (wdogTrigger) {
12933 getFailureData(&thread, failureStr, sizeof(failureStr));
12934
12935 if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12936 goto skip_stackshot;
12937 }
12938 } else {
12939 AbsoluteTime now;
12940 uint64_t nsec;
12941 clock_get_uptime(&now);
12942 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12943 absolutetime_to_nanoseconds(now, &nsec);
12944 snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12945 }
12946
12947 if (swd_buffer == NULL) {
12948 sleepWakeDebugMemAlloc();
12949 if (swd_buffer == NULL) {
12950 return;
12951 }
12952 }
12953 hdr = (swd_hdr *)swd_buffer;
12954 bufSize = hdr->alloc_size;
12955
12956 dstAddr = (char*)hdr + hdr->spindump_offset;
12957 flags = STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_THREAD_WAITINFO | STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12958
12959 /* If not wdogTrigger only take kernel tasks stackshot
12960 */
12961 if (wdogTrigger) {
12962 pid = -1;
12963 max_cnt = 3;
12964 } else {
12965 pid = 0;
12966 max_cnt = 2;
12967 }
12968
12969 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12970 * If we run out of space, take stackshot with only kernel task
12971 */
12972 while (success == 0 && cnt < max_cnt) {
12973 bytesRemaining = bufSize - hdr->spindump_offset;
12974 cnt++;
12975 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12976
12977 size = bytesRemaining;
12978 kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12979 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12980 kr, pid, size, flags, bytesWritten);
12981 if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12982 if (pid == -1) {
12983 pid = 0;
12984 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12985 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12986 } else {
12987 LOG("Insufficient buffer size for only kernel task\n");
12988 break;
12989 }
12990 }
12991 if (kr == KERN_SUCCESS) {
12992 if (bytesWritten == 0) {
12993 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12994 continue;
12995 }
12996 bytesRemaining -= bytesWritten;
12997 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12998
12999 memset(hdr->reason, 0x20, sizeof(hdr->reason));
13000
13001 // Compress stackshot and save to NVRAM
13002 {
13003 char *outbuf = (char *)swd_compressed_buffer;
13004 int outlen = 0;
13005 int num_chunks = 0;
13006 int max_chunks = 0;
13007 int leftover = 0;
13008 char nvram_var_name_buffer[20];
13009
13010 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
13011
13012 if (outlen) {
13013 max_chunks = outlen / (2096 - 200);
13014 leftover = outlen % (2096 - 200);
13015
13016 if (max_chunks < 8) {
13017 for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
13018 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
13019 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
13020 LOG("Failed to update NVRAM %d\n", num_chunks);
13021 break;
13022 }
13023 }
13024 if (leftover) {
13025 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
13026 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
13027 LOG("Failed to update NVRAM with leftovers\n");
13028 }
13029 }
13030 success = 1;
13031 LOG("Successfully saved stackshot to NVRAM\n");
13032 } else {
13033 if (pid == -1) {
13034 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
13035 pid = 0;
13036 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
13037 LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
13038 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
13039 } else {
13040 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
13041 break;
13042 }
13043 }
13044 }
13045 }
13046 }
13047 }
13048
13049 if (failureStr[0]) {
13050 // append sleep-wake failure code
13051 char traceCode[80];
13052 snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
13053 pmTracer->getTraceData(), pmTracer->getTracePhase());
13054 strlcat(failureStr, traceCode, sizeof(failureStr));
13055 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
13056 DLOG("Failed to write SleepWake failure string\n");
13057 }
13058 }
13059
13060 // force NVRAM sync
13061 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
13062 DLOG("Failed to force nvram sync\n");
13063 }
13064
13065 skip_stackshot:
13066 if (wdogTrigger) {
13067 if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
13068 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
13069 // If current boot is due to this watch dog trigger restart in previous boot,
13070 // then don't trigger again until at least 1 successful sleep & wake.
13071 if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
13072 LOG("Shutting down due to repeated Sleep/Wake failures\n");
13073 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
13074 PEHaltRestart(kPEHaltCPU);
13075 return;
13076 }
13077 }
13078 if (gSwdPanic == 0) {
13079 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
13080 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
13081 PEHaltRestart(kPERestartCPU);
13082 }
13083 }
13084 if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
13085 DLOG("Failed to write SleepWake failure panic key\n");
13086 }
13087 #if defined(__x86_64__)
13088 if (thread) {
13089 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
13090 } else
13091 #endif /* defined(__x86_64__) */
13092 {
13093 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
13094 }
13095 } else {
13096 gRootDomain->swd_lock = 0;
13097 return;
13098 }
13099 }
13100
13101 void
13102 IOPMrootDomain::sleepWakeDebugMemAlloc()
13103 {
13104 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
13105
13106 swd_hdr *hdr = NULL;
13107 void *bufPtr = NULL;
13108
13109 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
13110
13111
13112 if (kIOSleepWakeWdogOff & gIOKitDebug) {
13113 return;
13114 }
13115
13116 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
13117 return;
13118 }
13119
13120 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
13121 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
13122 size);
13123 if (memDesc == NULL) {
13124 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
13125 goto exit;
13126 }
13127
13128 bufPtr = memDesc->getBytesNoCopy();
13129
13130 // Carve out memory for zlib routines
13131 swd_zs_zmem = (vm_offset_t)bufPtr;
13132 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
13133
13134 // Carve out memory for compressed stackshots
13135 swd_compressed_buffer = bufPtr;
13136 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
13137
13138 // Remaining is used for holding stackshot
13139 hdr = (swd_hdr *)bufPtr;
13140 memset(hdr, 0, sizeof(swd_hdr));
13141
13142 hdr->signature = SWD_HDR_SIGNATURE;
13143 hdr->alloc_size = SWD_STACKSHOT_SIZE;
13144
13145 hdr->spindump_offset = sizeof(swd_hdr);
13146 swd_buffer = (void *)hdr;
13147 swd_memDesc = os::move(memDesc);
13148 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
13149
13150 exit:
13151 gRootDomain->swd_lock = 0;
13152 }
13153
13154 void
13155 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
13156 {
13157 #if UNUSED
13158 vm_size_t size = SWD_SPINDUMP_SIZE;
13159
13160 swd_hdr *hdr = NULL;
13161
13162 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
13163
13164 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
13165 return;
13166 }
13167
13168 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
13169 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
13170 SWD_SPINDUMP_SIZE);
13171
13172 if (memDesc == NULL) {
13173 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
13174 goto exit;
13175 }
13176
13177
13178 hdr = (swd_hdr *)memDesc->getBytesNoCopy();
13179 memset(hdr, 0, sizeof(swd_hdr));
13180
13181 hdr->signature = SWD_HDR_SIGNATURE;
13182 hdr->alloc_size = size;
13183
13184 hdr->spindump_offset = sizeof(swd_hdr);
13185 swd_spindump_buffer = (void *)hdr;
13186 swd_spindump_memDesc = os::move(memDesc);
13187
13188 exit:
13189 gRootDomain->swd_lock = 0;
13190 #endif /* UNUSED */
13191 }
13192
13193 void
13194 IOPMrootDomain::sleepWakeDebugEnableWdog()
13195 {
13196 }
13197
13198 bool
13199 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
13200 {
13201 return !systemBooting && !systemShutdown && !gWillShutdown;
13202 }
13203
13204 void
13205 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
13206 {
13207 swd_hdr *hdr = NULL;
13208 errno_t error = EIO;
13209
13210 if (swd_spindump_buffer && gSpinDumpBufferFull) {
13211 hdr = (swd_hdr *)swd_spindump_buffer;
13212
13213 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
13214 (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
13215
13216 if (error) {
13217 return;
13218 }
13219
13220 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
13221 (char*)hdr + offsetof(swd_hdr, UUID),
13222 sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
13223
13224 gSpinDumpBufferFull = false;
13225 }
13226 }
13227
13228 errno_t
13229 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
13230 {
13231 struct vnode *vp = NULL;
13232 vfs_context_t ctx = vfs_context_create(vfs_context_current());
13233 kauth_cred_t cred = vfs_context_ucred(ctx);
13234 struct vnode_attr va;
13235 errno_t error = EIO;
13236
13237 if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
13238 S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
13239 LOG("Failed to open the file %s\n", name);
13240 swd_flags |= SWD_FILEOP_ERROR;
13241 goto exit;
13242 }
13243 VATTR_INIT(&va);
13244 VATTR_WANTED(&va, va_nlink);
13245 /* Don't dump to non-regular files or files with links. */
13246 if (vp->v_type != VREG ||
13247 vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
13248 LOG("Bailing as this is not a regular file\n");
13249 swd_flags |= SWD_FILEOP_ERROR;
13250 goto exit;
13251 }
13252 VATTR_INIT(&va);
13253 VATTR_SET(&va, va_data_size, 0);
13254 vnode_setattr(vp, &va, ctx);
13255
13256
13257 if (buf != NULL) {
13258 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
13259 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
13260 if (error != 0) {
13261 LOG("Failed to save sleep wake log. err 0x%x\n", error);
13262 swd_flags |= SWD_FILEOP_ERROR;
13263 } else {
13264 DLOG("Saved %d bytes to file %s\n", len, name);
13265 }
13266 }
13267
13268 exit:
13269 if (vp) {
13270 vnode_close(vp, FWRITE, ctx);
13271 }
13272 if (ctx) {
13273 vfs_context_rele(ctx);
13274 }
13275
13276 return error;
13277 }
13278
13279 #else /* defined(__i386__) || defined(__x86_64__) */
13280
13281 void
13282 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
13283 {
13284 if (restart) {
13285 if (gSwdPanic == 0) {
13286 return;
13287 }
13288 panic("Sleep/Wake hang detected");
13289 return;
13290 }
13291 }
13292
13293 void
13294 IOPMrootDomain::takeStackshot(bool restart)
13295 {
13296 #pragma unused(restart)
13297 }
13298
13299 void
13300 IOPMrootDomain::deleteStackshot()
13301 {
13302 }
13303
13304 void
13305 IOPMrootDomain::sleepWakeDebugMemAlloc()
13306 {
13307 }
13308
13309 void
13310 IOPMrootDomain::saveFailureData2File()
13311 {
13312 }
13313
13314 void
13315 IOPMrootDomain::sleepWakeDebugEnableWdog()
13316 {
13317 }
13318
13319 bool
13320 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
13321 {
13322 return false;
13323 }
13324
13325 void
13326 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
13327 {
13328 }
13329
13330 errno_t
13331 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
13332 {
13333 return 0;
13334 }
13335
13336 #endif /* defined(__i386__) || defined(__x86_64__) */
13337
13338