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 "IOKitKernelInternal.h"
60 #if HIBERNATION
61 #include <IOKit/IOHibernatePrivate.h>
62 #endif /* HIBERNATION */
63 #include <machine/machine_routines.h>
64 #include <console/video_console.h>
65 #include <sys/syslog.h>
66 #include <sys/sysctl.h>
67 #include <sys/vnode.h>
68 #include <sys/vnode_internal.h>
69 #include <sys/fcntl.h>
70 #include <os/log.h>
71 #include <pexpert/protos.h>
72 #include <AssertMacros.h>
73
74 #include <sys/time.h>
75 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
76 #include "IOServicePMPrivate.h"
77
78 #include <libkern/zlib.h>
79 #include <os/cpp_util.h>
80 #include <os/atomic_private.h>
81 #include <libkern/c++/OSBoundedArrayRef.h>
82
83 #if DEVELOPMENT || DEBUG
84 #include <os/system_event_log.h>
85 #endif /* DEVELOPMENT || DEBUG */
86
87 __BEGIN_DECLS
88 #include <mach/shared_region.h>
89 #include <kern/clock.h>
90 #include <vm/vm_pageout_xnu.h>
91 __END_DECLS
92
93 #if defined(__i386__) || defined(__x86_64__)
94 __BEGIN_DECLS
95 #include "IOPMrootDomainInternal.h"
96 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
97 __END_DECLS
98 #endif
99
100 #define kIOPMrootDomainClass "IOPMrootDomain"
101 #define LOG_PREFIX "PMRD: "
102
103
104 #define MSG(x...) \
105 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
106
107 #define LOG(x...) \
108 do { kprintf(LOG_PREFIX x); } while (false)
109
110 #if DEVELOPMENT || DEBUG
111 #define DEBUG_LOG(x...) do { \
112 if (kIOLogPMRootDomain & gIOKitDebug) \
113 kprintf(LOG_PREFIX x); \
114 os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
115 } while (false)
116 #else
117 #define DEBUG_LOG(x...)
118 #endif
119
120 #define DLOG(x...) do { \
121 if (kIOLogPMRootDomain & gIOKitDebug) \
122 IOLog(LOG_PREFIX x); \
123 else \
124 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
125 } while (false)
126
127 #define DMSG(x...) do { \
128 if (kIOLogPMRootDomain & gIOKitDebug) { \
129 kprintf(LOG_PREFIX x); \
130 } \
131 } while (false)
132
133
134 #define _LOG(x...)
135
136 #define CHECK_THREAD_CONTEXT
137 #ifdef CHECK_THREAD_CONTEXT
138 static IOWorkLoop * gIOPMWorkLoop = NULL;
139 #define ASSERT_GATED() \
140 do { \
141 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
142 panic("RootDomain: not inside PM gate"); \
143 } \
144 } while(false)
145 #else
146 #define ASSERT_GATED()
147 #endif /* CHECK_THREAD_CONTEXT */
148
149 #define CAP_LOSS(c) \
150 (((_pendingCapability & (c)) == 0) && \
151 ((_currentCapability & (c)) != 0))
152
153 #define CAP_GAIN(c) \
154 (((_currentCapability & (c)) == 0) && \
155 ((_pendingCapability & (c)) != 0))
156
157 #define CAP_CHANGE(c) \
158 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
159
160 #define CAP_CURRENT(c) \
161 ((_currentCapability & (c)) != 0)
162
163 #define CAP_HIGHEST(c) \
164 ((_highestCapability & (c)) != 0)
165
166 #define CAP_PENDING(c) \
167 ((_pendingCapability & (c)) != 0)
168
169 // rdar://problem/9157444
170 #if defined(__i386__) || defined(__x86_64__)
171 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 20
172 #endif
173
174 // Event types for IOPMPowerStateQueue::submitPowerEvent()
175 enum {
176 kPowerEventFeatureChanged = 1, // 1
177 kPowerEventReceivedPowerNotification, // 2
178 kPowerEventSystemBootCompleted, // 3
179 kPowerEventSystemShutdown, // 4
180 kPowerEventUserDisabledSleep, // 5
181 kPowerEventRegisterSystemCapabilityClient, // 6
182 kPowerEventRegisterKernelCapabilityClient, // 7
183 kPowerEventPolicyStimulus, // 8
184 kPowerEventAssertionCreate, // 9
185 kPowerEventAssertionRelease, // 10
186 kPowerEventAssertionSetLevel, // 11
187 kPowerEventQueueSleepWakeUUID, // 12
188 kPowerEventPublishSleepWakeUUID, // 13
189 kPowerEventSetDisplayPowerOn, // 14
190 kPowerEventPublishWakeType, // 15
191 kPowerEventAOTEvaluate // 16
192 };
193
194 // For evaluatePolicy()
195 // List of stimuli that affects the root domain policy.
196 enum {
197 kStimulusDisplayWranglerSleep, // 0
198 kStimulusDisplayWranglerWake, // 1
199 kStimulusAggressivenessChanged, // 2
200 kStimulusDemandSystemSleep, // 3
201 kStimulusAllowSystemSleepChanged, // 4
202 kStimulusDarkWakeActivityTickle, // 5
203 kStimulusDarkWakeEntry, // 6
204 kStimulusDarkWakeReentry, // 7
205 kStimulusDarkWakeEvaluate, // 8
206 kStimulusNoIdleSleepPreventers, // 9
207 kStimulusEnterUserActiveState, // 10
208 kStimulusLeaveUserActiveState // 11
209 };
210
211 // Internal power state change reasons
212 // Must be less than kIOPMSleepReasonClamshell=101
213 enum {
214 kCPSReasonNone = 0, // 0
215 kCPSReasonInit, // 1
216 kCPSReasonWake, // 2
217 kCPSReasonIdleSleepPrevent, // 3
218 kCPSReasonIdleSleepAllow, // 4
219 kCPSReasonPowerOverride, // 5
220 kCPSReasonPowerDownCancel, // 6
221 kCPSReasonAOTExit, // 7
222 kCPSReasonAdjustPowerState, // 8
223 kCPSReasonDarkWakeCannotSleep, // 9
224 kCPSReasonIdleSleepEnabled, // 10
225 kCPSReasonEvaluatePolicy, // 11
226 kCPSReasonSustainFullWake, // 12
227 kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1)
228 };
229
230 extern "C" {
231 IOReturn OSKextSystemSleepOrWake( UInt32 );
232 }
233 extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
234 extern "C" addr64_t kvtophys(vm_offset_t va);
235 extern "C" boolean_t kdp_has_polled_corefile();
236
237 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
238 static void notifySystemShutdown( IOService * root, uint32_t messageType );
239 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
240 static void pmEventTimeStamp(uint64_t *recordTS);
241 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
242 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
243 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address);
244
245 static int IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt);
246 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
247 #define YMDTF "%04d/%02d/%d %02d:%02d:%02d"
248 #define YMDT(cal) ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
249
250 // "IOPMSetSleepSupported" callPlatformFunction name
251 static OSSharedPtr<const OSSymbol> sleepSupportedPEFunction;
252 static OSSharedPtr<const OSSymbol> sleepMessagePEFunction;
253 static OSSharedPtr<const OSSymbol> gIOPMWakeTypeUserKey;
254
255 static OSSharedPtr<const OSSymbol> gIOPMPSExternalConnectedKey;
256 static OSSharedPtr<const OSSymbol> gIOPMPSExternalChargeCapableKey;
257 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryInstalledKey;
258 static OSSharedPtr<const OSSymbol> gIOPMPSIsChargingKey;
259 static OSSharedPtr<const OSSymbol> gIOPMPSAtWarnLevelKey;
260 static OSSharedPtr<const OSSymbol> gIOPMPSAtCriticalLevelKey;
261 static OSSharedPtr<const OSSymbol> gIOPMPSCurrentCapacityKey;
262 static OSSharedPtr<const OSSymbol> gIOPMPSMaxCapacityKey;
263 static OSSharedPtr<const OSSymbol> gIOPMPSDesignCapacityKey;
264 static OSSharedPtr<const OSSymbol> gIOPMPSTimeRemainingKey;
265 static OSSharedPtr<const OSSymbol> gIOPMPSAmperageKey;
266 static OSSharedPtr<const OSSymbol> gIOPMPSVoltageKey;
267 static OSSharedPtr<const OSSymbol> gIOPMPSCycleCountKey;
268 static OSSharedPtr<const OSSymbol> gIOPMPSMaxErrKey;
269 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterInfoKey;
270 static OSSharedPtr<const OSSymbol> gIOPMPSLocationKey;
271 static OSSharedPtr<const OSSymbol> gIOPMPSErrorConditionKey;
272 static OSSharedPtr<const OSSymbol> gIOPMPSManufacturerKey;
273 static OSSharedPtr<const OSSymbol> gIOPMPSManufactureDateKey;
274 static OSSharedPtr<const OSSymbol> gIOPMPSModelKey;
275 static OSSharedPtr<const OSSymbol> gIOPMPSSerialKey;
276 static OSSharedPtr<const OSSymbol> gIOPMPSLegacyBatteryInfoKey;
277 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryHealthKey;
278 static OSSharedPtr<const OSSymbol> gIOPMPSHealthConfidenceKey;
279 static OSSharedPtr<const OSSymbol> gIOPMPSCapacityEstimatedKey;
280 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryChargeStatusKey;
281 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryTemperatureKey;
282 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsKey;
283 static OSSharedPtr<const OSSymbol> gIOPMPSChargerConfigurationKey;
284 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsIDKey;
285 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsWattsKey;
286 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsRevisionKey;
287 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSerialNumberKey;
288 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsFamilyKey;
289 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsAmperageKey;
290 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsDescriptionKey;
291 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsPMUConfigurationKey;
292 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSourceIDKey;
293 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsErrorFlagsKey;
294 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSharedSourceKey;
295 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsCloakedKey;
296 static OSSharedPtr<const OSSymbol> gIOPMPSInvalidWakeSecondsKey;
297 static OSSharedPtr<const OSSymbol> gIOPMPSPostChargeWaitSecondsKey;
298 static OSSharedPtr<const OSSymbol> gIOPMPSPostDishargeWaitSecondsKey;
299
300 #define kIOSleepSupportedKey "IOSleepSupported"
301 #define kIOPMSystemCapabilitiesKey "System Capabilities"
302 #define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
303
304 #define kIORequestWranglerIdleKey "IORequestIdle"
305 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
306
307 #define kIOSleepWakeFailureString "SleepWakeFailureString"
308 #define kIOEFIBootRomFailureKey "wake-failure"
309 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic"
310
311 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
312 | kIOPMSupportedOnBatt \
313 | kIOPMSupportedOnUPS)
314
315 #define kLocalEvalClamshellCommand (1 << 15)
316 #define kIdleSleepRetryInterval (3 * 60 * 1000)
317
318 // Minimum time in milliseconds after AP wake that we allow idle timer to expire.
319 // We impose this minimum to avoid race conditions in the AP wake path where
320 // userspace clients are not able to acquire power assertions before the idle timer expires.
321 #if XNU_TARGET_OS_IOS
322 #define kMinimumTimeBeforeIdleSleep 3000
323 #else
324 #define kMinimumTimeBeforeIdleSleep 1000
325 #endif
326
327 #define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID)
328
329 enum {
330 kWranglerPowerStateMin = 0,
331 kWranglerPowerStateSleep = 2,
332 kWranglerPowerStateDim = 3,
333 kWranglerPowerStateMax = 4
334 };
335
336 enum {
337 OFF_STATE = 0,
338 RESTART_STATE = 1,
339 SLEEP_STATE = 2,
340 AOT_STATE = 3,
341 ON_STATE = 4,
342 NUM_POWER_STATES
343 };
344
345 const char *
getPowerStateString(uint32_t state)346 getPowerStateString( uint32_t state )
347 {
348 #define POWER_STATE(x) {(uint32_t) x, #x}
349
350 static const IONamedValue powerStates[] = {
351 POWER_STATE( OFF_STATE ),
352 POWER_STATE( RESTART_STATE ),
353 POWER_STATE( SLEEP_STATE ),
354 POWER_STATE( AOT_STATE ),
355 POWER_STATE( ON_STATE ),
356 { 0, NULL }
357 };
358 return IOFindNameForValue(state, powerStates);
359 }
360
361 #define ON_POWER kIOPMPowerOn
362 #define RESTART_POWER kIOPMRestart
363 #define SLEEP_POWER kIOPMAuxPowerOn
364
365 static IOPMPowerState
366 ourPowerStates[NUM_POWER_STATES] =
367 {
368 { .version = 1,
369 .capabilityFlags = 0,
370 .outputPowerCharacter = 0,
371 .inputPowerRequirement = 0 },
372 { .version = 1,
373 .capabilityFlags = kIOPMRestartCapability,
374 .outputPowerCharacter = kIOPMRestart,
375 .inputPowerRequirement = RESTART_POWER },
376 { .version = 1,
377 .capabilityFlags = kIOPMSleepCapability,
378 .outputPowerCharacter = kIOPMSleep,
379 .inputPowerRequirement = SLEEP_POWER },
380 { .version = 1,
381 .capabilityFlags = kIOPMAOTCapability,
382 .outputPowerCharacter = kIOPMAOTPower,
383 .inputPowerRequirement = ON_POWER },
384 { .version = 1,
385 .capabilityFlags = kIOPMPowerOn,
386 .outputPowerCharacter = kIOPMPowerOn,
387 .inputPowerRequirement = ON_POWER },
388 };
389
390 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
391 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
392 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
393 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
394 #define kIOPMRootDomainWakeTypeUser "User"
395 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
396 #define kIOPMRootDomainWakeTypeNetwork "Network"
397 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
398 #define kIOPMRootDomainWakeTypeNotification "Notification"
399 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
400
401 // Special interest that entitles the interested client from receiving
402 // all system messages. Only used by powerd.
403 //
404 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
405
406 // Entitlement required for root domain clients
407 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
408
409 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
410 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
411
412 /*
413 * Aggressiveness
414 */
415 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
416 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
417
418 #define kAggressivesMinValue 1
419
420 const char *
getAggressivenessTypeString(uint32_t type)421 getAggressivenessTypeString( uint32_t type )
422 {
423 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
424
425 static const IONamedValue aggressivenessTypes[] = {
426 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ),
427 AGGRESSIVENESS_TYPE( kPMMinutesToDim ),
428 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ),
429 AGGRESSIVENESS_TYPE( kPMMinutesToSleep ),
430 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ),
431 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ),
432 AGGRESSIVENESS_TYPE( kPMPowerSource),
433 AGGRESSIVENESS_TYPE( kPMMotionSensor ),
434 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ),
435 { 0, NULL }
436 };
437 return IOFindNameForValue(type, aggressivenessTypes);
438 }
439
440 enum {
441 kAggressivesStateBusy = 0x01,
442 kAggressivesStateQuickSpindown = 0x02
443 };
444
445 struct AggressivesRecord {
446 uint32_t flags;
447 uint32_t type;
448 uint32_t value;
449 };
450
451 struct AggressivesRequest {
452 queue_chain_t chain;
453 uint32_t options;
454 uint32_t dataType;
455 union {
456 OSSharedPtr<IOService> service;
457 AggressivesRecord record;
458 } data;
459 };
460
461 enum {
462 kAggressivesRequestTypeService = 1,
463 kAggressivesRequestTypeRecord
464 };
465
466 enum {
467 kAggressivesOptionSynchronous = 0x00000001,
468 kAggressivesOptionQuickSpindownEnable = 0x00000100,
469 kAggressivesOptionQuickSpindownDisable = 0x00000200,
470 kAggressivesOptionQuickSpindownMask = 0x00000300
471 };
472
473 enum {
474 kAggressivesRecordFlagModified = 0x00000001,
475 kAggressivesRecordFlagMinValue = 0x00000002
476 };
477
478 // System Sleep Preventers
479
480 enum {
481 kPMUserDisabledAllSleep = 1,
482 kPMSystemRestartBootingInProgress,
483 kPMConfigPreventSystemSleep,
484 kPMChildPreventSystemSleep,
485 kPMCPUAssertion,
486 kPMPCIUnsupported,
487 kPMDKNotReady,
488 };
489
490 const char *
getSystemSleepPreventerString(uint32_t preventer)491 getSystemSleepPreventerString( uint32_t preventer )
492 {
493 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
494 static const IONamedValue systemSleepPreventers[] = {
495 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ),
496 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ),
497 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ),
498 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ),
499 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ),
500 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ),
501 SYSTEM_SLEEP_PREVENTER( kPMDKNotReady ),
502 { 0, NULL }
503 };
504 return IOFindNameForValue(preventer, systemSleepPreventers);
505 }
506
507 // gDarkWakeFlags
508 enum {
509 kDarkWakeFlagPromotionNone = 0x0000,
510 kDarkWakeFlagPromotionEarly = 0x0001, // promote before gfx clamp
511 kDarkWakeFlagPromotionLate = 0x0002, // promote after gfx clamp
512 kDarkWakeFlagPromotionMask = 0x0003,
513 kDarkWakeFlagAlarmIsDark = 0x0100,
514 kDarkWakeFlagAudioNotSuppressed = 0x0200,
515 kDarkWakeFlagUserWakeWorkaround = 0x1000
516 };
517
518 // gClamshellFlags
519 // The workaround for 9157444 is enabled at compile time using the
520 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below.
521 enum {
522 kClamshell_WAR_38378787 = 0x00000001,
523 kClamshell_WAR_47715679 = 0x00000002,
524 kClamshell_WAR_58009435 = 0x00000004
525 };
526
527 // acceptSystemWakeEvents()
528 enum {
529 kAcceptSystemWakeEvents_Disable = 0,
530 kAcceptSystemWakeEvents_Enable,
531 kAcceptSystemWakeEvents_Reenable
532 };
533
534 static IOPMrootDomain * gRootDomain;
535 static IORootParent * gPatriarch;
536 static IONotifier * gSysPowerDownNotifier = NULL;
537 static UInt32 gSleepOrShutdownPending = 0;
538 static UInt32 gWillShutdown = 0;
539 static UInt32 gPagingOff = 0;
540 static UInt32 gSleepWakeUUIDIsSet = false;
541 static uint32_t gAggressivesState = 0;
542 uint32_t gHaltTimeMaxLog;
543 uint32_t gHaltTimeMaxPanic;
544 IOLock * gHaltLogLock;
545 static char * gHaltLog;
546 enum { kHaltLogSize = 2048 };
547 static size_t gHaltLogPos;
548 static uint64_t gHaltStartTime;
549 static char gKextNameBuf[64];
550 static size_t gKextNamePos;
551 static bool gKextNameEnd;
552
553 uuid_string_t bootsessionuuid_string;
554
555 #if defined(XNU_TARGET_OS_OSX)
556 #if DISPLAY_WRANGLER_PRESENT
557 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionNone;
558 #elif defined(__arm64__)
559 // Enable temporary full wake promotion workarounds
560 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
561 #else
562 // Enable full wake promotion workarounds
563 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
564 #endif
565 #else /* !defined(XNU_TARGET_OS_OSX) */
566 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionEarly;
567 #endif /* !defined(XNU_TARGET_OS_OSX) */
568
569 static uint32_t gNoIdleFlag = 0;
570 static uint32_t gSleepDisabledFlag = 0;
571 static uint32_t gSwdPanic = 1;
572 static uint32_t gSwdSleepTimeout = 0;
573 static uint32_t gSwdWakeTimeout = 0;
574 static uint32_t gSwdSleepWakeTimeout = 0;
575 static PMStatsStruct gPMStats;
576 #if DEVELOPMENT || DEBUG
577 static uint32_t swd_panic_phase;
578 #endif
579
580 static uint32_t gClamshellFlags = 0
581 #if defined(__i386__) || defined(__x86_64__)
582 | kClamshell_WAR_58009435
583 #endif
584 ;
585
586 #if HIBERNATION
587
588 #if defined(__arm64__)
589 static IOReturn
defaultSleepPolicyHandler(void * ctx,const IOPMSystemSleepPolicyVariables * vars,IOPMSystemSleepParameters * params)590 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params)
591 {
592 uint32_t sleepType = kIOPMSleepTypeDeepIdle;
593
594 assert(vars->signature == kIOPMSystemSleepPolicySignature);
595 assert(vars->version == kIOPMSystemSleepPolicyVersion);
596
597 // Hibernation enabled and either user forced hibernate or low battery sleep
598 if ((vars->hibernateMode & kIOHibernateModeOn) &&
599 (((vars->hibernateMode & kIOHibernateModeSleep) == 0) ||
600 (vars->sleepFactors & kIOPMSleepFactorBatteryLow))) {
601 sleepType = kIOPMSleepTypeHibernate;
602 }
603 params->version = kIOPMSystemSleepParametersVersion;
604 params->sleepType = sleepType;
605 return kIOReturnSuccess;
606 }
607 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = &defaultSleepPolicyHandler;
608 #else /* defined(__arm64__) */
609 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = NULL;
610 #endif /* defined(__arm64__) */
611
612 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
613 static void * gSleepPolicyTarget;
614 #endif
615
616 struct timeval gIOLastSleepTime;
617 struct timeval gIOLastWakeTime;
618 AbsoluteTime gIOLastWakeAbsTime;
619 AbsoluteTime gIOLastSleepAbsTime;
620
621 struct timeval gIOLastUserSleepTime;
622
623 static char gWakeReasonString[128];
624 static char gBootReasonString[80];
625 static char gShutdownReasonString[80];
626 static bool gWakeReasonSysctlRegistered = false;
627 static bool gBootReasonSysctlRegistered = false;
628 static bool gShutdownReasonSysctlRegistered = false;
629 static bool gWillShutdownSysctlRegistered = false;
630 static AbsoluteTime gUserActiveAbsTime;
631 static AbsoluteTime gUserInactiveAbsTime;
632
633 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
634 static bool gSpinDumpBufferFull = false;
635 #endif
636
637 z_stream swd_zs;
638 vm_offset_t swd_zs_zmem;
639 //size_t swd_zs_zsize;
640 size_t swd_zs_zoffset;
641 #if defined(__i386__) || defined(__x86_64__)
642 IOCPU *currentShutdownTarget = NULL;
643 #endif
644
645 static unsigned int gPMHaltBusyCount;
646 static unsigned int gPMHaltIdleCount;
647 static int gPMHaltDepth;
648 static uint32_t gPMHaltMessageType;
649 static IOLock * gPMHaltLock = NULL;
650 static OSSharedPtr<OSArray> gPMHaltArray;
651 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey;
652 static bool gPMQuiesced;
653
654 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
655 #define kCPUUnknownIndex 9999999
656 enum {
657 kInformAC = 0,
658 kInformLid = 1,
659 kInformableCount = 2
660 };
661
662 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut;
663 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel;
664 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow;
665 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt;
666 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow;
667
668 #define kBadPMFeatureID 0
669
670 /*
671 * PMSettingHandle
672 * Opaque handle passed to clients of registerPMSettingController()
673 */
674 class PMSettingHandle : public OSObject
675 {
676 OSDeclareFinalStructors( PMSettingHandle );
677 friend class PMSettingObject;
678
679 private:
680 PMSettingObject *pmso;
681 void free(void) APPLE_KEXT_OVERRIDE;
682 };
683
684 /*
685 * PMSettingObject
686 * Internal object to track each PM setting controller
687 */
688 class PMSettingObject : public OSObject
689 {
690 OSDeclareFinalStructors( PMSettingObject );
691 friend class IOPMrootDomain;
692
693 private:
694 queue_head_t calloutQueue;
695 thread_t waitThread;
696 IOPMrootDomain *parent;
697 PMSettingHandle *pmsh;
698 IOPMSettingControllerCallback func;
699 OSObject *target;
700 uintptr_t refcon;
701 OSDataAllocation<uint32_t> publishedFeatureID;
702 uint32_t settingCount;
703 bool disabled;
704
705 void free(void) APPLE_KEXT_OVERRIDE;
706
707 public:
708 static PMSettingObject *pmSettingObject(
709 IOPMrootDomain *parent_arg,
710 IOPMSettingControllerCallback handler_arg,
711 OSObject *target_arg,
712 uintptr_t refcon_arg,
713 uint32_t supportedPowerSources,
714 const OSSymbol *settings[],
715 OSObject **handle_obj);
716
717 IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
718 void clientHandleFreed(void);
719 };
720
721 struct PMSettingCallEntry {
722 queue_chain_t link;
723 thread_t thread;
724 };
725
726 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
727 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
728 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
729 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
730
731 /*
732 * PMTraceWorker
733 * Internal helper object for logging trace points to RTC
734 * IOPMrootDomain and only IOPMrootDomain should instantiate
735 * exactly one of these.
736 */
737
738 typedef void (*IOPMTracePointHandler)(
739 void * target, uint32_t code, uint32_t data );
740
741 class PMTraceWorker : public OSObject
742 {
743 OSDeclareDefaultStructors(PMTraceWorker);
744 public:
745 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
746
747 static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * );
748 void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
749 void tracePoint(uint8_t phase);
750 void traceDetail(uint32_t detail);
751 void traceComponentWakeProgress(uint32_t component, uint32_t data);
752 int recordTopLevelPCIDevice(IOService *);
753 void RTC_TRACE(void);
754 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
755
756 IOPMTracePointHandler tracePointHandler;
757 void * tracePointTarget;
758 uint64_t getPMStatusCode();
759 uint8_t getTracePhase();
760 uint32_t getTraceData();
761 private:
762 IOPMrootDomain *owner;
763 IOLock *pmTraceWorkerLock;
764 OSSharedPtr<OSArray> pciDeviceBitMappings;
765
766 uint8_t addedToRegistry;
767 uint8_t tracePhase;
768 uint32_t traceData32;
769 uint8_t loginWindowData;
770 uint8_t coreDisplayData;
771 uint8_t coreGraphicsData;
772 };
773
774 /*
775 * this should be treated as POD, as it's byte-copied around
776 * and we cannot rely on d'tor firing at the right time
777 */
778 struct PMAssertStruct {
779 IOPMDriverAssertionID id;
780 IOPMDriverAssertionType assertionBits;
781 uint64_t createdTime;
782 uint64_t modifiedTime;
783 const OSSymbol *ownerString;
784 IOService *ownerService;
785 uint64_t registryEntryID;
786 IOPMDriverAssertionLevel level;
787 uint64_t assertCPUStartTime;
788 uint64_t assertCPUDuration;
789 };
790 OSDefineValueObjectForDependentType(PMAssertStruct)
791
792 /*
793 * PMAssertionsTracker
794 * Tracks kernel and user space PM assertions
795 */
796 class PMAssertionsTracker : public OSObject
797 {
798 OSDeclareFinalStructors(PMAssertionsTracker);
799 public:
800 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * );
801
802 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
803 IOReturn releaseAssertion(IOPMDriverAssertionID);
804 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
805 IOReturn setUserAssertionLevels(IOPMDriverAssertionType);
806
807 OSSharedPtr<OSArray> copyAssertionsArray(void);
808 IOPMDriverAssertionType getActivatedAssertions(void);
809 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType);
810
811 IOReturn handleCreateAssertion(OSValueObject<PMAssertStruct> *);
812 IOReturn handleReleaseAssertion(IOPMDriverAssertionID);
813 IOReturn handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
814 IOReturn handleSetUserAssertionLevels(void * arg0);
815 void publishProperties(void);
816 void reportCPUBitAccounting(void);
817 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *);
818
819 private:
820 uint32_t tabulateProducerCount;
821 uint32_t tabulateConsumerCount;
822
823 uint64_t maxAssertCPUDuration;
824 uint64_t maxAssertCPUEntryId;
825
826 void tabulate(void);
827 void updateCPUBitAccounting(PMAssertStruct * assertStruct);
828
829 IOPMrootDomain *owner;
830 OSSharedPtr<OSArray> assertionsArray;
831 IOLock *assertionsArrayLock;
832 IOPMDriverAssertionID issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
833 IOPMDriverAssertionType assertionsKernel;
834 IOPMDriverAssertionType assertionsUser;
835 IOPMDriverAssertionType assertionsCombined;
836 };
837
838 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
839
840 /*
841 * PMHaltWorker
842 * Internal helper object for Shutdown/Restart notifications.
843 */
844 #define kPMHaltMaxWorkers 8
845 #define kPMHaltTimeoutMS 100
846
847 class PMHaltWorker : public OSObject
848 {
849 OSDeclareFinalStructors( PMHaltWorker );
850
851 public:
852 IOService * service;// service being worked on
853 AbsoluteTime startTime; // time when work started
854 int depth; // work on nubs at this PM-tree depth
855 int visits; // number of nodes visited (debug)
856 IOLock * lock;
857 bool timeout;// service took too long
858
859 static PMHaltWorker * worker( void );
860 static void main( void * arg, wait_result_t waitResult );
861 static void work( PMHaltWorker * me );
862 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
863 virtual void free( void ) APPLE_KEXT_OVERRIDE;
864 };
865
OSDefineMetaClassAndFinalStructors(PMHaltWorker,OSObject)866 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
867
868
869 #define super IOService
870 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
871
872 boolean_t
873 IOPMRootDomainGetWillShutdown(void)
874 {
875 return gWillShutdown != 0;
876 }
877
878 static void
IOPMRootDomainWillShutdown(void)879 IOPMRootDomainWillShutdown(void)
880 {
881 if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
882 IOService::willShutdown();
883 for (int i = 0; i < 100; i++) {
884 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
885 break;
886 }
887 IOSleep( 100 );
888 }
889 }
890 }
891
892 extern "C" IONotifier *
registerSleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)893 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
894 {
895 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
896 }
897
898 extern "C" IONotifier *
registerPrioritySleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)899 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
900 {
901 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
902 }
903
904 extern "C" IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon)905 acknowledgeSleepWakeNotification(void * PMrefcon)
906 {
907 return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
908 }
909
910 extern "C" IOReturn
vetoSleepWakeNotification(void * PMrefcon)911 vetoSleepWakeNotification(void * PMrefcon)
912 {
913 return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
914 }
915
916 extern "C" IOReturn
rootDomainRestart(void)917 rootDomainRestart( void )
918 {
919 return gRootDomain->restartSystem();
920 }
921
922 extern "C" IOReturn
rootDomainShutdown(void)923 rootDomainShutdown( void )
924 {
925 return gRootDomain->shutdownSystem();
926 }
927
928 static void
halt_log_putc(char c)929 halt_log_putc(char c)
930 {
931 if (gHaltLogPos >= (kHaltLogSize - 2)) {
932 return;
933 }
934 gHaltLog[gHaltLogPos++] = c;
935 }
936
937 extern "C" void
938 _doprnt_log(const char *fmt,
939 va_list *argp,
940 void (*putc)(char),
941 int radix);
942
943 static int
halt_log(const char * fmt,...)944 halt_log(const char *fmt, ...)
945 {
946 va_list listp;
947
948 va_start(listp, fmt);
949 _doprnt_log(fmt, &listp, &halt_log_putc, 16);
950 va_end(listp);
951
952 return 0;
953 }
954
955 extern "C" void
halt_log_enter(const char * what,const void * pc,uint64_t time)956 halt_log_enter(const char * what, const void * pc, uint64_t time)
957 {
958 uint64_t nano, millis;
959
960 if (!gHaltLog) {
961 return;
962 }
963 absolutetime_to_nanoseconds(time, &nano);
964 millis = nano / NSEC_PER_MSEC;
965 if (millis < 100) {
966 return;
967 }
968
969 IOLockLock(gHaltLogLock);
970 if (pc) {
971 halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
972 OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
973 OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
974 } else {
975 halt_log("%s: %qd ms\n", what, millis);
976 }
977
978 gHaltLog[gHaltLogPos] = 0;
979 IOLockUnlock(gHaltLogLock);
980 }
981
982 extern uint32_t gFSState;
983
984 extern "C" void
IOSystemShutdownNotification(int howto,int stage)985 IOSystemShutdownNotification(int howto, int stage)
986 {
987 uint64_t startTime;
988
989 if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
990 #if defined(XNU_TARGET_OS_OSX)
991 uint64_t nano, millis;
992 startTime = mach_absolute_time();
993 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
994 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
995 millis = nano / NSEC_PER_MSEC;
996 if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
997 printf("waitQuiet() for unmount %qd ms\n", millis);
998 }
999 #endif /* defined(XNU_TARGET_OS_OSX) */
1000 return;
1001 }
1002
1003 if (kIOSystemShutdownNotificationTerminateDEXTs == stage) {
1004 uint64_t nano, millis;
1005 startTime = mach_absolute_time();
1006 IOServicePH::systemHalt(howto);
1007 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
1008 millis = nano / NSEC_PER_MSEC;
1009 if (true || (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog))) {
1010 printf("IOServicePH::systemHalt took %qd ms\n", millis);
1011 }
1012 return;
1013 }
1014
1015 assert(kIOSystemShutdownNotificationStageProcessExit == stage);
1016
1017 IOLockLock(gHaltLogLock);
1018 if (!gHaltLog) {
1019 gHaltLog = IONewData(char, (vm_size_t)kHaltLogSize);
1020 gHaltStartTime = mach_absolute_time();
1021 if (gHaltLog) {
1022 halt_log_putc('\n');
1023 }
1024 }
1025 IOLockUnlock(gHaltLogLock);
1026
1027 startTime = mach_absolute_time();
1028 IOPMRootDomainWillShutdown();
1029 halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
1030 #if HIBERNATION
1031 startTime = mach_absolute_time();
1032 IOHibernateSystemPostWake(true);
1033 halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
1034 #endif
1035 if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1036 gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1037 }
1038 }
1039
1040 extern "C" int sync_internal(void);
1041
1042 /*
1043 * A device is always in the highest power state which satisfies its driver,
1044 * its policy-maker, and any power children it has, but within the constraint
1045 * of the power state provided by its parent. The driver expresses its desire by
1046 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
1047 * changePowerStateToPriv(), and the children express their desires by calling
1048 * requestPowerDomainState().
1049 *
1050 * The Root Power Domain owns the policy for idle and demand sleep for the system.
1051 * It is a power-managed IOService just like the others in the system.
1052 * It implements several power states which map to what we see as Sleep and On.
1053 *
1054 * The sleep policy is as follows:
1055 * 1. Sleep is prevented if the case is open so that nobody will think the machine
1056 * is off and plug/unplug cards.
1057 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1058 * 3. System cannot Sleep if some object in the tree is in a power state marked
1059 * kIOPMPreventSystemSleep.
1060 *
1061 * These three conditions are enforced using the "driver clamp" by calling
1062 * changePowerStateTo(). For example, if the case is opened,
1063 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
1064 * of the desires of the children of the root or the state of the other clamp.
1065 *
1066 * Demand Sleep is initiated by pressing the front panel power button, closing
1067 * the clamshell, or selecting the menu item. In this case the root's parent
1068 * actually initiates the power state change so that the root domain has no
1069 * choice and does not give applications the opportunity to veto the change.
1070 *
1071 * Idle Sleep occurs if no objects in the tree are in a state marked
1072 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
1073 * the root on, so it sets the "policy-maker clamp" by calling
1074 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1075 * This timer is set for the difference between the sleep timeout slider and the
1076 * display dim timeout slider. When the timer expires, it releases its clamp and
1077 * now nothing is holding it awake, so it falls asleep.
1078 *
1079 * Demand sleep is prevented when the system is booting. When preferences are
1080 * transmitted by the loginwindow at the end of boot, a flag is cleared,
1081 * and this allows subsequent Demand Sleep.
1082 */
1083
1084 //******************************************************************************
1085
1086 IOPMrootDomain *
construct(void)1087 IOPMrootDomain::construct( void )
1088 {
1089 IOPMrootDomain *root;
1090
1091 root = new IOPMrootDomain;
1092 if (root) {
1093 root->init();
1094 }
1095
1096 return root;
1097 }
1098
1099 //******************************************************************************
1100 // updateConsoleUsersCallout
1101 //
1102 //******************************************************************************
1103
1104 static void
updateConsoleUsersCallout(thread_call_param_t p0,thread_call_param_t p1)1105 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1106 {
1107 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1108 rootDomain->updateConsoleUsers();
1109 }
1110
1111 void
updateConsoleUsers(void)1112 IOPMrootDomain::updateConsoleUsers(void)
1113 {
1114 IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1115 updateTasksSuspend(kTasksSuspendUnsuspended, kTasksSuspendNoChange);
1116 }
1117
1118 bool
updateTasksSuspend(int newTasksSuspended,int newAOTTasksSuspended)1119 IOPMrootDomain::updateTasksSuspend(int newTasksSuspended, int newAOTTasksSuspended)
1120 {
1121 bool newSuspend;
1122
1123 WAKEEVENT_LOCK();
1124 if (newTasksSuspended != kTasksSuspendNoChange) {
1125 tasksSuspended = (newTasksSuspended != kTasksSuspendUnsuspended);
1126 }
1127 if (newAOTTasksSuspended != kTasksSuspendNoChange) {
1128 _aotTasksSuspended = (newAOTTasksSuspended != kTasksSuspendUnsuspended);
1129 }
1130 newSuspend = (tasksSuspended || _aotTasksSuspended);
1131 if (newSuspend == tasksSuspendState) {
1132 WAKEEVENT_UNLOCK();
1133 return false;
1134 }
1135 tasksSuspendState = newSuspend;
1136 WAKEEVENT_UNLOCK();
1137 tasks_system_suspend(newSuspend);
1138 return true;
1139 }
1140
1141 //******************************************************************************
1142
1143 static void
disk_sync_callout(thread_call_param_t p0,thread_call_param_t p1)1144 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1145 {
1146 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1147 uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
1148 uint32_t powerState = rootDomain->getPowerState();
1149
1150 DLOG("disk_sync_callout ps=%u\n", powerState);
1151
1152 if (ON_STATE == powerState) {
1153 sync_internal();
1154
1155 #if HIBERNATION
1156 // Block sleep until trim issued on previous wake path is completed.
1157 IOHibernateSystemPostWake(true);
1158 #endif
1159 }
1160 #if HIBERNATION
1161 else {
1162 IOHibernateSystemPostWake(false);
1163
1164 rootDomain->sleepWakeDebugSaveSpinDumpFile();
1165 }
1166 #endif
1167
1168 rootDomain->allowPowerChange(notifyRef);
1169 DLOG("disk_sync_callout finish\n");
1170 }
1171
1172 //******************************************************************************
1173 static UInt32
computeDeltaTimeMS(const AbsoluteTime * startTime,AbsoluteTime * elapsedTime)1174 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1175 {
1176 AbsoluteTime endTime;
1177 UInt64 nano = 0;
1178
1179 clock_get_uptime(&endTime);
1180 if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1181 *elapsedTime = 0;
1182 } else {
1183 SUB_ABSOLUTETIME(&endTime, startTime);
1184 absolutetime_to_nanoseconds(endTime, &nano);
1185 *elapsedTime = endTime;
1186 }
1187
1188 return (UInt32)(nano / NSEC_PER_MSEC);
1189 }
1190
1191 //******************************************************************************
1192
1193 static int
1194 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1195 {
1196 struct timeval *swt = (struct timeval *)arg1;
1197 struct proc *p = req->p;
1198
1199 if (p == kernproc) {
1200 return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
1201 } else if (proc_is64bit(p)) {
1202 struct user64_timeval t = {};
1203 t.tv_sec = swt->tv_sec;
1204 t.tv_usec = swt->tv_usec;
1205 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1206 } else {
1207 struct user32_timeval t = {};
1208 t.tv_sec = (typeof(t.tv_sec))swt->tv_sec;
1209 t.tv_usec = swt->tv_usec;
1210 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1211 }
1212 }
1213
1214 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1215 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1216 &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1217
1218 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1219 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1220 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1221
1222 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
1223 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
1224 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
1225 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
1226
1227 static int
1228 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1229 {
1230 int new_value, changed, error;
1231
1232 if (!gWillShutdownSysctlRegistered) {
1233 return ENOENT;
1234 }
1235
1236 error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1237 if (changed) {
1238 if (!gWillShutdown && (new_value == 1)) {
1239 IOPMRootDomainWillShutdown();
1240 } else {
1241 error = EINVAL;
1242 }
1243 }
1244 return error;
1245 }
1246
1247 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1248 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1249 NULL, 0, sysctl_willshutdown, "I", "");
1250
1251 #if defined(XNU_TARGET_OS_OSX)
1252
1253 static int
sysctl_progressmeterenable(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1254 sysctl_progressmeterenable
1255 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1256 {
1257 int error;
1258 int new_value, changed;
1259
1260 error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1261
1262 if (changed) {
1263 vc_enable_progressmeter(new_value);
1264 }
1265
1266 return error;
1267 }
1268
1269 static int
sysctl_progressmeter(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1270 sysctl_progressmeter
1271 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1272 {
1273 int error;
1274 int new_value, changed;
1275
1276 error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1277
1278 if (changed) {
1279 vc_set_progressmeter(new_value);
1280 }
1281
1282 return error;
1283 }
1284
1285 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1286 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1287 NULL, 0, sysctl_progressmeterenable, "I", "");
1288
1289 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1290 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1291 NULL, 0, sysctl_progressmeter, "I", "");
1292
1293 #endif /* defined(XNU_TARGET_OS_OSX) */
1294
1295
1296
1297 static int
sysctl_consoleoptions(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1298 sysctl_consoleoptions
1299 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1300 {
1301 int error, changed;
1302 uint32_t new_value;
1303
1304 error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1305
1306 if (changed) {
1307 vc_user_options.options = new_value;
1308 }
1309
1310 return error;
1311 }
1312
1313 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1314 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1315 NULL, 0, sysctl_consoleoptions, "I", "");
1316
1317
1318 static int
1319 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1320 {
1321 return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1322 }
1323
1324 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1325 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1326 NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1327
1328
1329 static int
1330 sysctl_wakereason SYSCTL_HANDLER_ARGS
1331 {
1332 char wr[sizeof(gWakeReasonString)];
1333
1334 wr[0] = '\0';
1335 if (gRootDomain && gWakeReasonSysctlRegistered) {
1336 gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1337 } else {
1338 return ENOENT;
1339 }
1340
1341 return sysctl_io_string(req, wr, 0, 0, NULL);
1342 }
1343
1344 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1345 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1346 NULL, 0, sysctl_wakereason, "A", "wakereason");
1347
1348 static int
1349 sysctl_bootreason SYSCTL_HANDLER_ARGS
1350 {
1351 if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) {
1352 return ENOENT;
1353 }
1354
1355 return sysctl_io_string(req, gBootReasonString, 0, 0, NULL);
1356 }
1357
1358 SYSCTL_PROC(_kern, OID_AUTO, bootreason,
1359 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1360 NULL, 0, sysctl_bootreason, "A", "");
1361
1362 static int
1363 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1364 {
1365 char sr[sizeof(gShutdownReasonString)];
1366
1367 sr[0] = '\0';
1368 if (gRootDomain && gShutdownReasonSysctlRegistered) {
1369 gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1370 } else {
1371 return ENOENT;
1372 }
1373
1374 return sysctl_io_string(req, sr, 0, 0, NULL);
1375 }
1376
1377 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1378 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1379 NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1380
1381 static int
1382 sysctl_targettype SYSCTL_HANDLER_ARGS
1383 {
1384 IOService * root;
1385 OSSharedPtr<OSObject> obj;
1386 OSData * data;
1387 char tt[32];
1388
1389 tt[0] = '\0';
1390 root = IOService::getServiceRoot();
1391 if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1392 if ((data = OSDynamicCast(OSData, obj.get()))) {
1393 strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1394 }
1395 }
1396 return sysctl_io_string(req, tt, 0, 0, NULL);
1397 }
1398
1399 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1400 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1401 NULL, 0, sysctl_targettype, "A", "targettype");
1402
1403 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1404 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1405 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1406 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1407 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1408 #if DEVELOPMENT || DEBUG
1409 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
1410 #if defined(XNU_TARGET_OS_OSX)
1411 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, "");
1412 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1413 #endif /* defined(XNU_TARGET_OS_OSX) */
1414 #endif /* DEVELOPMENT || DEBUG */
1415
1416 //******************************************************************************
1417 // AOT
1418
1419 static int
1420 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1421 {
1422 if (NULL == gRootDomain) {
1423 return ENOENT;
1424 }
1425 if (NULL == gRootDomain->_aotMetrics) {
1426 IOPMAOTMetrics nullMetrics = {};
1427 return sysctl_io_opaque(req, &nullMetrics, sizeof(IOPMAOTMetrics), NULL);
1428 }
1429 return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1430 }
1431
1432 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
1433 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1434 NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
1435
1436
1437 static int
update_aotmode(uint32_t mode)1438 update_aotmode(uint32_t mode)
1439 {
1440 int result;
1441
1442 if (!gIOPMWorkLoop) {
1443 return ENOENT;
1444 }
1445 result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1446 unsigned int oldCount;
1447
1448 if (mode && !gRootDomain->_aotMetrics) {
1449 gRootDomain->_aotMetrics = IOMallocType(IOPMAOTMetrics);
1450 }
1451
1452 oldCount = gRootDomain->idleSleepPreventersCount();
1453 gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1454 gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1455 return 0;
1456 });
1457 return result;
1458 }
1459
1460 static int
sysctl_aotmodebits(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1461 sysctl_aotmodebits
1462 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1463 {
1464 int error, changed;
1465 uint32_t new_value;
1466
1467 if (NULL == gRootDomain) {
1468 return ENOENT;
1469 }
1470 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1471 if (changed && gIOPMWorkLoop) {
1472 error = update_aotmode(new_value);
1473 }
1474
1475 return error;
1476 }
1477
1478 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1479 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1480 NULL, 0, sysctl_aotmodebits, "I", "");
1481
1482 static int
sysctl_aotmode(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1483 sysctl_aotmode
1484 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1485 {
1486 int error, changed;
1487 uint32_t new_value;
1488
1489 if (NULL == gRootDomain) {
1490 return ENOENT;
1491 }
1492 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1493 if (changed && gIOPMWorkLoop) {
1494 if (new_value) {
1495 new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1496 }
1497 error = update_aotmode(new_value);
1498 }
1499
1500 return error;
1501 }
1502
1503 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
1504 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1505 NULL, 0, sysctl_aotmode, "I", "");
1506
1507 //******************************************************************************
1508
1509 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey;
1510 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey;
1511 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey;
1512 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey;
1513 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey;
1514 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey;
1515 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey;
1516 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey;
1517 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey;
1518 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey;
1519 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey;
1520 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey;
1521
1522 //******************************************************************************
1523 // start
1524 //
1525 //******************************************************************************
1526
1527 #define kRootDomainSettingsCount 20
1528 #define kRootDomainNoPublishSettingsCount 4
1529
1530 bool
start(IOService * nub)1531 IOPMrootDomain::start( IOService * nub )
1532 {
1533 OSSharedPtr<OSIterator> psIterator;
1534 OSSharedPtr<OSDictionary> tmpDict;
1535
1536 super::start(nub);
1537
1538 gRootDomain = this;
1539 gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1540 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1541 gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
1542 gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
1543 gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1544 gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
1545 gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1546 gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1547 gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1548 gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1549 gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1550 gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey);
1551
1552 gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1553 gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1554 gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1555 gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1556 gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1557
1558 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1559 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1560 gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1561
1562 OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1563 {
1564 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1565 gIOPMSettingAutoWakeSecondsKey,
1566 gIOPMSettingAutoPowerSecondsKey,
1567 gIOPMSettingAutoWakeCalendarKey,
1568 gIOPMSettingAutoPowerCalendarKey,
1569 gIOPMSettingDebugWakeRelativeKey,
1570 gIOPMSettingDebugPowerRelativeKey,
1571 OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1572 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1573 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1574 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1575 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1576 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1577 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1578 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1579 OSSymbol::withCString(kIOPMStateConsoleShutdown),
1580 OSSymbol::withCString(kIOPMSettingProModeControl),
1581 OSSymbol::withCString(kIOPMSettingProModeDefer),
1582 gIOPMSettingSilentRunningKey,
1583 gIOPMSettingLowLatencyAudioModeKey,
1584 };
1585
1586 OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1587 {
1588 OSSymbol::withCString(kIOPMSettingProModeControl),
1589 OSSymbol::withCString(kIOPMSettingProModeDefer),
1590 gIOPMSettingSilentRunningKey,
1591 gIOPMSettingLowLatencyAudioModeKey,
1592 };
1593
1594 #if DEVELOPMENT || DEBUG
1595 #if defined(XNU_TARGET_OS_OSX)
1596 PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1597 PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags));
1598 #endif /* defined(XNU_TARGET_OS_OSX) */
1599 #endif /* DEVELOPMENT || DEBUG */
1600
1601 PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1602 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1603 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1604 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1605 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1606 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1607
1608 // read noidle setting from Device Tree
1609 if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
1610 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
1611 }
1612
1613 queue_init(&aggressivesQueue);
1614 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1615 aggressivesData = OSData::withCapacity(
1616 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1617
1618 featuresDictLock = IOLockAlloc();
1619 settingsCtrlLock = IOLockAlloc();
1620 wakeEventLock = IOLockAlloc();
1621 gHaltLogLock = IOLockAlloc();
1622 setPMRootDomain(this);
1623
1624 extraSleepTimer = thread_call_allocate(
1625 idleSleepTimerExpired,
1626 (thread_call_param_t) this);
1627
1628 powerButtonDown = thread_call_allocate(
1629 powerButtonDownCallout,
1630 (thread_call_param_t) this);
1631
1632 powerButtonUp = thread_call_allocate(
1633 powerButtonUpCallout,
1634 (thread_call_param_t) this);
1635
1636 diskSyncCalloutEntry = thread_call_allocate(
1637 &disk_sync_callout,
1638 (thread_call_param_t) this);
1639 updateConsoleUsersEntry = thread_call_allocate(
1640 &updateConsoleUsersCallout,
1641 (thread_call_param_t) this);
1642
1643 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1644 fullWakeThreadCall = thread_call_allocate_with_options(
1645 OSMemberFunctionCast(thread_call_func_t, this,
1646 &IOPMrootDomain::fullWakeDelayedWork),
1647 (thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL,
1648 THREAD_CALL_OPTIONS_ONCE);
1649 #endif
1650
1651 setProperty(kIOSleepSupportedKey, true);
1652
1653 bzero(&gPMStats, sizeof(gPMStats));
1654
1655 pmTracer = PMTraceWorker::tracer(this);
1656
1657 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1658
1659 userDisabledAllSleep = false;
1660 systemBooting = true;
1661 idleSleepEnabled = false;
1662 idleSleepRevertible = true;
1663 sleepSlider = 0;
1664 idleSleepTimerPending = false;
1665 wrangler = NULL;
1666 clamshellClosed = false;
1667 clamshellExists = false;
1668 #if DISPLAY_WRANGLER_PRESENT
1669 clamshellDisabled = true;
1670 #else
1671 clamshellDisabled = false;
1672 #endif
1673 clamshellIgnoreClose = false;
1674 acAdaptorConnected = true;
1675 clamshellSleepDisableMask = 0;
1676 gWakeReasonString[0] = '\0';
1677
1678 // Initialize to user active.
1679 // Will never transition to user inactive w/o wrangler.
1680 fullWakeReason = kFullWakeReasonLocalUser;
1681 userIsActive = userWasActive = true;
1682 clock_get_uptime(&gUserActiveAbsTime);
1683 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
1684
1685 // Set the default system capabilities at boot.
1686 _currentCapability = kIOPMSystemCapabilityCPU |
1687 kIOPMSystemCapabilityGraphics |
1688 kIOPMSystemCapabilityAudio |
1689 kIOPMSystemCapabilityNetwork;
1690
1691 _pendingCapability = _currentCapability;
1692 _desiredCapability = _currentCapability;
1693 _highestCapability = _currentCapability;
1694 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1695
1696 queuedSleepWakeUUIDString = NULL;
1697 initializeBootSessionUUID();
1698 pmStatsAppResponses = OSArray::withCapacity(5);
1699 _statsNameKey = OSSymbol::withCString(kIOPMStatsNameKey);
1700 _statsPIDKey = OSSymbol::withCString(kIOPMStatsPIDKey);
1701 _statsTimeMSKey = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1702 _statsResponseTypeKey = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1703 _statsMessageTypeKey = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1704 _statsPowerCapsKey = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1705 assertOnWakeSecs = -1;// Invalid value to prevent updates
1706
1707 pmStatsLock = IOLockAlloc();
1708 idxPMCPUClamshell = kCPUUnknownIndex;
1709 idxPMCPULimitedPower = kCPUUnknownIndex;
1710
1711 tmpDict = OSDictionary::withCapacity(1);
1712 setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1713
1714 // Set a default "SystemPowerProfileOverrideDict" for platform
1715 // drivers without any overrides.
1716 if (!propertyExists(kIOPMSystemDefaultOverrideKey)) {
1717 tmpDict = OSDictionary::withCapacity(1);
1718 setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get());
1719 }
1720
1721 settingsCallbacks = OSDictionary::withCapacity(1);
1722
1723 // Create a list of the valid PM settings that we'll relay to
1724 // interested clients in setProperties() => setPMSetting()
1725 allowedPMSettings = OSArray::withObjects(
1726 (const OSObject **)settingsArr,
1727 kRootDomainSettingsCount,
1728 0);
1729
1730 // List of PM settings that should not automatically publish itself
1731 // as a feature when registered by a listener.
1732 noPublishPMSettings = OSArray::withObjects(
1733 (const OSObject **)noPublishSettingsArr,
1734 kRootDomainNoPublishSettingsCount,
1735 0);
1736
1737 fPMSettingsDict = OSDictionary::withCapacity(5);
1738 preventIdleSleepList = OSSet::withCapacity(8);
1739 preventSystemSleepList = OSSet::withCapacity(2);
1740
1741 PMinit(); // creates gIOPMWorkLoop
1742 gIOPMWorkLoop = getIOPMWorkloop();
1743
1744 // Create IOPMPowerStateQueue used to queue external power
1745 // events, and to handle those events on the PM work loop.
1746 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1747 this, OSMemberFunctionCast(IOEventSource::Action, this,
1748 &IOPMrootDomain::dispatchPowerEvent));
1749 gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1750
1751 _aotMode = 0;
1752 _aotTimerES = IOTimerEventSource::timerEventSource(this,
1753 OSMemberFunctionCast(IOTimerEventSource::Action,
1754 this, &IOPMrootDomain::aotEvaluate));
1755 gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1756
1757 // Avoid publishing service early so gIOPMWorkLoop is
1758 // guaranteed to be initialized by rootDomain.
1759 publishPMRootDomain();
1760
1761 // create our power parent
1762 gPatriarch = new IORootParent;
1763 gPatriarch->init();
1764 gPatriarch->attach(this);
1765 gPatriarch->start(this);
1766 gPatriarch->addPowerChild(this);
1767
1768 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1769 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1770
1771 // install power change handler
1772 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1773
1774 #if DISPLAY_WRANGLER_PRESENT
1775 wranglerIdleSettings = OSDictionary::withCapacity(1);
1776 OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1777
1778 if (wranglerIdleSettings && wranglerIdlePeriod) {
1779 wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1780 wranglerIdlePeriod.get());
1781 }
1782
1783 #endif /* DISPLAY_WRANGLER_PRESENT */
1784
1785 lowLatencyAudioNotifierDict = OSDictionary::withCapacity(2);
1786 lowLatencyAudioNotifyStateSym = OSSymbol::withCString("LowLatencyAudioNotifyState");
1787 lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1788 lowLatencyAudioNotifyStateVal = OSNumber::withNumber(0ull, 32);
1789 lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64);
1790
1791 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1792 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1793 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1794 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1795 }
1796
1797 OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1798 setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1799
1800 // IOBacklightDisplay can take a long time to load at boot, or it may
1801 // not load at all if you're booting with clamshell closed. We publish
1802 // 'DisplayDims' here redundantly to get it published early and at all.
1803 OSSharedPtr<OSDictionary> matching;
1804 matching = serviceMatching("IOPMPowerSource");
1805 psIterator = getMatchingServices(matching.get());
1806
1807 if (psIterator && psIterator->getNextObject()) {
1808 // There's at least one battery on the system, so we publish
1809 // 'DisplayDims' support for the LCD.
1810 publishFeature("DisplayDims");
1811 }
1812
1813 // read swd_panic boot-arg
1814 PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1815 gWillShutdownSysctlRegistered = true;
1816
1817 #if HIBERNATION
1818 IOHibernateSystemInit(this);
1819 #endif
1820
1821 registerService(); // let clients find us
1822
1823 return true;
1824 }
1825
1826 //******************************************************************************
1827 // setProperties
1828 //
1829 // Receive a setProperty call
1830 // The "System Boot" property means the system is completely booted.
1831 //******************************************************************************
1832
1833 IOReturn
setProperties(OSObject * props_obj)1834 IOPMrootDomain::setProperties( OSObject * props_obj )
1835 {
1836 IOReturn return_value = kIOReturnSuccess;
1837 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
1838 OSBoolean *b = NULL;
1839 OSNumber *n = NULL;
1840 const OSSymbol *key = NULL;
1841 OSObject *obj = NULL;
1842 OSSharedPtr<OSCollectionIterator> iter;
1843
1844 if (!dict) {
1845 return kIOReturnBadArgument;
1846 }
1847
1848 bool clientEntitled = false;
1849 {
1850 OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1851 clientEntitled = (obj == kOSBooleanTrue);
1852 }
1853
1854 if (!clientEntitled) {
1855 const char * errorSuffix = NULL;
1856
1857 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1858 // That API can set 6 possible keys that are checked below.
1859 if ((dict->getCount() == 1) &&
1860 (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) ||
1861 dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) ||
1862 dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) ||
1863 dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) ||
1864 dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) ||
1865 dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) {
1866 return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
1867 if (return_value != kIOReturnSuccess) {
1868 errorSuffix = "privileged";
1869 }
1870 } else {
1871 return_value = kIOReturnNotPermitted;
1872 errorSuffix = "entitled";
1873 }
1874
1875 if (return_value != kIOReturnSuccess) {
1876 OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain);
1877 DLOG("%s failed, process %s is not %s\n", __func__,
1878 procName ? procName->getCStringNoCopy() : "", errorSuffix);
1879 return return_value;
1880 }
1881 }
1882
1883 OSSharedPtr<const OSSymbol> publish_simulated_battery_string = OSSymbol::withCString("SoftwareSimulatedBatteries");
1884 OSSharedPtr<const OSSymbol> boot_complete_string = OSSymbol::withCString("System Boot Complete");
1885 OSSharedPtr<const OSSymbol> sys_shutdown_string = OSSymbol::withCString("System Shutdown");
1886 OSSharedPtr<const OSSymbol> stall_halt_string = OSSymbol::withCString("StallSystemAtHalt");
1887 OSSharedPtr<const OSSymbol> battery_warning_disabled_string = OSSymbol::withCString("BatteryWarningsDisabled");
1888 OSSharedPtr<const OSSymbol> idle_seconds_string = OSSymbol::withCString("System Idle Seconds");
1889 OSSharedPtr<const OSSymbol> idle_milliseconds_string = OSSymbol::withCString("System Idle Milliseconds");
1890 OSSharedPtr<const OSSymbol> sleepdisabled_string = OSSymbol::withCString("SleepDisabled");
1891 OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1892 OSSharedPtr<const OSSymbol> loginwindow_progress_string = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1893 OSSharedPtr<const OSSymbol> coredisplay_progress_string = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1894 OSSharedPtr<const OSSymbol> coregraphics_progress_string = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1895 #if DEBUG || DEVELOPMENT
1896 OSSharedPtr<const OSSymbol> clamshell_close_string = OSSymbol::withCString("IOPMTestClamshellClose");
1897 OSSharedPtr<const OSSymbol> clamshell_open_string = OSSymbol::withCString("IOPMTestClamshellOpen");
1898 OSSharedPtr<const OSSymbol> ac_detach_string = OSSymbol::withCString("IOPMTestACDetach");
1899 OSSharedPtr<const OSSymbol> ac_attach_string = OSSymbol::withCString("IOPMTestACAttach");
1900 OSSharedPtr<const OSSymbol> desktopmode_set_string = OSSymbol::withCString("IOPMTestDesktopModeSet");
1901 OSSharedPtr<const OSSymbol> desktopmode_remove_string = OSSymbol::withCString("IOPMTestDesktopModeRemove");
1902 #endif
1903
1904 #if HIBERNATION
1905 OSSharedPtr<const OSSymbol> hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey);
1906 OSSharedPtr<const OSSymbol> hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey);
1907 OSSharedPtr<const OSSymbol> hibernatefilemin_string = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
1908 OSSharedPtr<const OSSymbol> hibernatefilemax_string = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
1909 OSSharedPtr<const OSSymbol> hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey);
1910 OSSharedPtr<const OSSymbol> hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey);
1911 #endif
1912
1913 iter = OSCollectionIterator::withCollection(dict);
1914 if (!iter) {
1915 return_value = kIOReturnNoMemory;
1916 goto exit;
1917 }
1918
1919 while ((key = (const OSSymbol *) iter->getNextObject()) &&
1920 (obj = dict->getObject(key))) {
1921 if (key->isEqualTo(publish_simulated_battery_string.get())) {
1922 if (OSDynamicCast(OSBoolean, obj)) {
1923 publishResource(key, kOSBooleanTrue);
1924 }
1925 } else if (key->isEqualTo(idle_seconds_string.get())) {
1926 if ((n = OSDynamicCast(OSNumber, obj))) {
1927 setProperty(key, n);
1928 idleMilliSeconds = n->unsigned32BitValue() * 1000;
1929 }
1930 } else if (key->isEqualTo(idle_milliseconds_string.get())) {
1931 if ((n = OSDynamicCast(OSNumber, obj))) {
1932 setProperty(key, n);
1933 idleMilliSeconds = n->unsigned32BitValue();
1934 }
1935 } else if (key->isEqualTo(boot_complete_string.get())) {
1936 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
1937 } else if (key->isEqualTo(sys_shutdown_string.get())) {
1938 if ((b = OSDynamicCast(OSBoolean, obj))) {
1939 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
1940 }
1941 } else if (key->isEqualTo(battery_warning_disabled_string.get())) {
1942 setProperty(key, obj);
1943 }
1944 #if HIBERNATION
1945 else if (key->isEqualTo(hibernatemode_string.get()) ||
1946 key->isEqualTo(hibernatefilemin_string.get()) ||
1947 key->isEqualTo(hibernatefilemax_string.get()) ||
1948 key->isEqualTo(hibernatefreeratio_string.get()) ||
1949 key->isEqualTo(hibernatefreetime_string.get())) {
1950 if ((n = OSDynamicCast(OSNumber, obj))) {
1951 setProperty(key, n);
1952 }
1953 } else if (key->isEqualTo(hibernatefile_string.get())) {
1954 OSString * str = OSDynamicCast(OSString, obj);
1955 if (str) {
1956 setProperty(key, str);
1957 }
1958 }
1959 #endif
1960 else if (key->isEqualTo(sleepdisabled_string.get())) {
1961 if ((b = OSDynamicCast(OSBoolean, obj))) {
1962 setProperty(key, b);
1963 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1964 }
1965 } else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
1966 obj->retain();
1967 pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
1968 } else if (key->isEqualTo(loginwindow_progress_string.get())) {
1969 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1970 uint32_t data = n->unsigned32BitValue();
1971 pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
1972 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
1973 }
1974 } else if (key->isEqualTo(coredisplay_progress_string.get())) {
1975 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1976 uint32_t data = n->unsigned32BitValue();
1977 pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
1978 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
1979 }
1980 } else if (key->isEqualTo(coregraphics_progress_string.get())) {
1981 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1982 uint32_t data = n->unsigned32BitValue();
1983 pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
1984 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
1985 }
1986 } else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
1987 key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
1988 key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
1989 key->isEqualTo(stall_halt_string.get())) {
1990 if ((b = OSDynamicCast(OSBoolean, obj))) {
1991 setProperty(key, b);
1992 }
1993 } else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
1994 key->isEqualTo(kIOPMDeepSleepTimerKey) ||
1995 key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
1996 key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
1997 if ((n = OSDynamicCast(OSNumber, obj))) {
1998 setProperty(key, n);
1999 }
2000 } else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
2001 if (kOSBooleanTrue == obj) {
2002 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2003 } else {
2004 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2005 }
2006 DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
2007 }
2008 #if DEBUG || DEVELOPMENT
2009 else if (key->isEqualTo(clamshell_close_string.get())) {
2010 DLOG("SetProperties: setting clamshell close\n");
2011 UInt32 msg = kIOPMClamshellClosed;
2012 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2013 } else if (key->isEqualTo(clamshell_open_string.get())) {
2014 DLOG("SetProperties: setting clamshell open\n");
2015 UInt32 msg = kIOPMClamshellOpened;
2016 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2017 } else if (key->isEqualTo(ac_detach_string.get())) {
2018 DLOG("SetProperties: setting ac detach\n");
2019 UInt32 msg = kIOPMSetACAdaptorConnected;
2020 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2021 } else if (key->isEqualTo(ac_attach_string.get())) {
2022 DLOG("SetProperties: setting ac attach\n");
2023 UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue;
2024 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2025 } else if (key->isEqualTo(desktopmode_set_string.get())) {
2026 DLOG("SetProperties: setting desktopmode");
2027 UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue;
2028 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2029 } else if (key->isEqualTo(desktopmode_remove_string.get())) {
2030 DLOG("SetProperties: removing desktopmode\n");
2031 UInt32 msg = kIOPMSetDesktopMode;
2032 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2033 }
2034 #endif
2035 // Relay our allowed PM settings onto our registered PM clients
2036 else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
2037 return_value = setPMSetting(key, obj);
2038 if (kIOReturnSuccess != return_value) {
2039 break;
2040 }
2041 } else {
2042 DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
2043 }
2044 }
2045
2046 exit:
2047 return return_value;
2048 }
2049
2050 // MARK: -
2051 // MARK: Aggressiveness
2052
2053 //******************************************************************************
2054 // setAggressiveness
2055 //
2056 // Override IOService::setAggressiveness()
2057 //******************************************************************************
2058
2059 IOReturn
setAggressiveness(unsigned long type,unsigned long value)2060 IOPMrootDomain::setAggressiveness(
2061 unsigned long type,
2062 unsigned long value )
2063 {
2064 return setAggressiveness( type, value, 0 );
2065 }
2066
2067 /*
2068 * Private setAggressiveness() with an internal options argument.
2069 */
2070 IOReturn
setAggressiveness(unsigned long type,unsigned long value,IOOptionBits options)2071 IOPMrootDomain::setAggressiveness(
2072 unsigned long type,
2073 unsigned long value,
2074 IOOptionBits options )
2075 {
2076 AggressivesRequest * entry;
2077 AggressivesRequest * request;
2078 bool found = false;
2079
2080 if ((type > UINT_MAX) || (value > UINT_MAX)) {
2081 return kIOReturnBadArgument;
2082 }
2083
2084 if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2085 DLOG("setAggressiveness(%x) %s = %u\n",
2086 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2087 } else {
2088 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2089 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2090 }
2091
2092 request = IOMallocType(AggressivesRequest);
2093 request->options = options;
2094 request->dataType = kAggressivesRequestTypeRecord;
2095 request->data.record.type = (uint32_t) type;
2096 request->data.record.value = (uint32_t) value;
2097
2098 AGGRESSIVES_LOCK();
2099
2100 // Update disk quick spindown flag used by getAggressiveness().
2101 // Never merge requests with quick spindown flags set.
2102
2103 if (options & kAggressivesOptionQuickSpindownEnable) {
2104 gAggressivesState |= kAggressivesStateQuickSpindown;
2105 } else if (options & kAggressivesOptionQuickSpindownDisable) {
2106 gAggressivesState &= ~kAggressivesStateQuickSpindown;
2107 } else {
2108 // Coalesce requests with identical aggressives types.
2109 // Deal with callers that calls us too "aggressively".
2110
2111 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2112 {
2113 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2114 (entry->data.record.type == type) &&
2115 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2116 entry->data.record.value = (uint32_t) value;
2117 found = true;
2118 break;
2119 }
2120 }
2121 }
2122
2123 if (!found) {
2124 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2125 }
2126
2127 AGGRESSIVES_UNLOCK();
2128
2129 if (found) {
2130 IOFreeType(request, AggressivesRequest);
2131 }
2132
2133 if (options & kAggressivesOptionSynchronous) {
2134 handleAggressivesRequests(); // not truly synchronous
2135 } else {
2136 thread_call_enter(aggressivesThreadCall);
2137 }
2138
2139 return kIOReturnSuccess;
2140 }
2141
2142 //******************************************************************************
2143 // getAggressiveness
2144 //
2145 // Override IOService::setAggressiveness()
2146 // Fetch the aggressiveness factor with the given type.
2147 //******************************************************************************
2148
2149 IOReturn
getAggressiveness(unsigned long type,unsigned long * outLevel)2150 IOPMrootDomain::getAggressiveness(
2151 unsigned long type,
2152 unsigned long * outLevel )
2153 {
2154 uint32_t value = 0;
2155 int source = 0;
2156
2157 if (!outLevel || (type > UINT_MAX)) {
2158 return kIOReturnBadArgument;
2159 }
2160
2161 AGGRESSIVES_LOCK();
2162
2163 // Disk quick spindown in effect, report value = 1
2164
2165 if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2166 (type == kPMMinutesToSpinDown)) {
2167 value = kAggressivesMinValue;
2168 source = 1;
2169 }
2170
2171 // Consult the pending request queue.
2172
2173 if (!source) {
2174 AggressivesRequest * entry;
2175
2176 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2177 {
2178 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2179 (entry->data.record.type == type) &&
2180 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2181 value = entry->data.record.value;
2182 source = 2;
2183 break;
2184 }
2185 }
2186 }
2187
2188 // Consult the backend records.
2189
2190 if (!source && aggressivesData) {
2191 AggressivesRecord * record;
2192 int i, count;
2193
2194 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2195 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2196
2197 for (i = 0; i < count; i++, record++) {
2198 if (record->type == type) {
2199 value = record->value;
2200 source = 3;
2201 break;
2202 }
2203 }
2204 }
2205
2206 AGGRESSIVES_UNLOCK();
2207
2208 if (source) {
2209 *outLevel = (unsigned long) value;
2210 return kIOReturnSuccess;
2211 } else {
2212 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
2213 *outLevel = 0; // default return = 0, driver may not check for error
2214 return kIOReturnInvalid;
2215 }
2216 }
2217
2218 //******************************************************************************
2219 // joinAggressiveness
2220 //
2221 // Request from IOService to join future aggressiveness broadcasts.
2222 //******************************************************************************
2223
2224 IOReturn
joinAggressiveness(IOService * service)2225 IOPMrootDomain::joinAggressiveness(
2226 IOService * service )
2227 {
2228 AggressivesRequest * request;
2229
2230 if (!service || (service == this)) {
2231 return kIOReturnBadArgument;
2232 }
2233
2234 DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2235
2236 request = IOMallocType(AggressivesRequest);
2237 request->dataType = kAggressivesRequestTypeService;
2238 request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2239
2240 AGGRESSIVES_LOCK();
2241 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2242 AGGRESSIVES_UNLOCK();
2243
2244 thread_call_enter(aggressivesThreadCall);
2245
2246 return kIOReturnSuccess;
2247 }
2248
2249 //******************************************************************************
2250 // handleAggressivesRequests
2251 //
2252 // Backend thread processes all incoming aggressiveness requests in the queue.
2253 //******************************************************************************
2254
2255 static void
handleAggressivesFunction(thread_call_param_t param1,thread_call_param_t param2)2256 handleAggressivesFunction(
2257 thread_call_param_t param1,
2258 thread_call_param_t param2 )
2259 {
2260 if (param1) {
2261 ((IOPMrootDomain *) param1)->handleAggressivesRequests();
2262 }
2263 }
2264
2265 void
handleAggressivesRequests(void)2266 IOPMrootDomain::handleAggressivesRequests( void )
2267 {
2268 AggressivesRecord * start;
2269 AggressivesRecord * record;
2270 AggressivesRequest * request;
2271 queue_head_t joinedQueue;
2272 int i, count;
2273 bool broadcast;
2274 bool found;
2275 bool pingSelf = false;
2276
2277 AGGRESSIVES_LOCK();
2278
2279 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2280 queue_empty(&aggressivesQueue)) {
2281 goto unlock_done;
2282 }
2283
2284 gAggressivesState |= kAggressivesStateBusy;
2285 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2286 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2287
2288 do{
2289 broadcast = false;
2290 queue_init(&joinedQueue);
2291
2292 do{
2293 // Remove request from the incoming queue in FIFO order.
2294 queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
2295 switch (request->dataType) {
2296 case kAggressivesRequestTypeRecord:
2297 // Update existing record if found.
2298 found = false;
2299 for (i = 0, record = start; i < count; i++, record++) {
2300 if (record->type == request->data.record.type) {
2301 found = true;
2302
2303 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2304 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2305 broadcast = true;
2306 record->flags |= (kAggressivesRecordFlagMinValue |
2307 kAggressivesRecordFlagModified);
2308 DLOG("disk spindown accelerated, was %u min\n",
2309 record->value);
2310 }
2311 } else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2312 if (record->flags & kAggressivesRecordFlagMinValue) {
2313 broadcast = true;
2314 record->flags |= kAggressivesRecordFlagModified;
2315 record->flags &= ~kAggressivesRecordFlagMinValue;
2316 DLOG("disk spindown restored to %u min\n",
2317 record->value);
2318 }
2319 } else if (record->value != request->data.record.value) {
2320 record->value = request->data.record.value;
2321 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2322 broadcast = true;
2323 record->flags |= kAggressivesRecordFlagModified;
2324 }
2325 }
2326 break;
2327 }
2328 }
2329
2330 // No matching record, append a new record.
2331 if (!found &&
2332 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2333 AggressivesRecord newRecord;
2334
2335 newRecord.flags = kAggressivesRecordFlagModified;
2336 newRecord.type = request->data.record.type;
2337 newRecord.value = request->data.record.value;
2338 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2339 newRecord.flags |= kAggressivesRecordFlagMinValue;
2340 DLOG("disk spindown accelerated\n");
2341 }
2342
2343 aggressivesData->appendValue(newRecord);
2344
2345 // OSData may have switched to another (larger) buffer.
2346 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2347 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2348 broadcast = true;
2349 }
2350
2351 // Finished processing the request, release it.
2352 IOFreeType(request, AggressivesRequest);
2353 break;
2354
2355 case kAggressivesRequestTypeService:
2356 // synchronizeAggressives() will free request.
2357 queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2358 break;
2359
2360 default:
2361 panic("bad aggressives request type %x", request->dataType);
2362 break;
2363 }
2364 } while (!queue_empty(&aggressivesQueue));
2365
2366 // Release the lock to perform work, with busy flag set.
2367 if (!queue_empty(&joinedQueue) || broadcast) {
2368 AGGRESSIVES_UNLOCK();
2369 if (!queue_empty(&joinedQueue)) {
2370 synchronizeAggressives(&joinedQueue, start, count);
2371 }
2372 if (broadcast) {
2373 broadcastAggressives(start, count);
2374 }
2375 AGGRESSIVES_LOCK();
2376 }
2377
2378 // Remove the modified flag from all records.
2379 for (i = 0, record = start; i < count; i++, record++) {
2380 if ((record->flags & kAggressivesRecordFlagModified) &&
2381 ((record->type == kPMMinutesToDim) ||
2382 (record->type == kPMMinutesToSleep))) {
2383 pingSelf = true;
2384 }
2385
2386 record->flags &= ~kAggressivesRecordFlagModified;
2387 }
2388
2389 // Check the incoming queue again since new entries may have been
2390 // added while lock was released above.
2391 } while (!queue_empty(&aggressivesQueue));
2392
2393 gAggressivesState &= ~kAggressivesStateBusy;
2394
2395 unlock_done:
2396 AGGRESSIVES_UNLOCK();
2397
2398 // Root domain is interested in system and display sleep slider changes.
2399 // Submit a power event to handle those changes on the PM work loop.
2400
2401 if (pingSelf && pmPowerStateQueue) {
2402 pmPowerStateQueue->submitPowerEvent(
2403 kPowerEventPolicyStimulus,
2404 (void *) kStimulusAggressivenessChanged );
2405 }
2406 }
2407
2408 //******************************************************************************
2409 // synchronizeAggressives
2410 //
2411 // Push all known aggressiveness records to one or more IOService.
2412 //******************************************************************************
2413
2414 void
synchronizeAggressives(queue_head_t * joinedQueue,const AggressivesRecord * array,int count)2415 IOPMrootDomain::synchronizeAggressives(
2416 queue_head_t * joinedQueue,
2417 const AggressivesRecord * array,
2418 int count )
2419 {
2420 OSSharedPtr<IOService> service;
2421 AggressivesRequest * request;
2422 const AggressivesRecord * record;
2423 IOPMDriverCallEntry callEntry;
2424 uint32_t value;
2425 int i;
2426
2427 while (!queue_empty(joinedQueue)) {
2428 queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
2429 if (request->dataType == kAggressivesRequestTypeService) {
2430 // retained by joinAggressiveness(), so take ownership
2431 service = os::move(request->data.service);
2432 } else {
2433 service.reset();
2434 }
2435
2436 IOFreeType(request, AggressivesRequest);
2437 request = NULL;
2438
2439 if (service) {
2440 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2441 for (i = 0, record = array; i < count; i++, record++) {
2442 value = record->value;
2443 if (record->flags & kAggressivesRecordFlagMinValue) {
2444 value = kAggressivesMinValue;
2445 }
2446
2447 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2448 record->type, value, service->getName());
2449 service->setAggressiveness(record->type, value);
2450 }
2451 service->deassertPMDriverCall(&callEntry);
2452 }
2453 }
2454 }
2455 }
2456
2457 //******************************************************************************
2458 // broadcastAggressives
2459 //
2460 // Traverse PM tree and call setAggressiveness() for records that have changed.
2461 //******************************************************************************
2462
2463 void
broadcastAggressives(const AggressivesRecord * array,int count)2464 IOPMrootDomain::broadcastAggressives(
2465 const AggressivesRecord * array,
2466 int count )
2467 {
2468 OSSharedPtr<IORegistryIterator> iter;
2469 IORegistryEntry *entry;
2470 OSSharedPtr<IORegistryEntry> child;
2471 IOPowerConnection *connect;
2472 IOService *service;
2473 const AggressivesRecord *record;
2474 IOPMDriverCallEntry callEntry;
2475 uint32_t value;
2476 int i;
2477
2478 iter = IORegistryIterator::iterateOver(
2479 this, gIOPowerPlane, kIORegistryIterateRecursively);
2480 if (iter) {
2481 do{
2482 // !! reset the iterator
2483 iter->reset();
2484 while ((entry = iter->getNextObject())) {
2485 connect = OSDynamicCast(IOPowerConnection, entry);
2486 if (!connect || !connect->getReadyFlag()) {
2487 continue;
2488 }
2489
2490 child = connect->copyChildEntry(gIOPowerPlane);
2491 if (child) {
2492 if ((service = OSDynamicCast(IOService, child.get()))) {
2493 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2494 for (i = 0, record = array; i < count; i++, record++) {
2495 if (record->flags & kAggressivesRecordFlagModified) {
2496 value = record->value;
2497 if (record->flags & kAggressivesRecordFlagMinValue) {
2498 value = kAggressivesMinValue;
2499 }
2500 _LOG("broadcastAggressives %x = %u to %s\n",
2501 record->type, value, service->getName());
2502 service->setAggressiveness(record->type, value);
2503 }
2504 }
2505 service->deassertPMDriverCall(&callEntry);
2506 }
2507 }
2508 }
2509 }
2510 }while (!entry && !iter->isValid());
2511 }
2512 }
2513
2514 //*****************************************
2515 // stackshot on power button press
2516 // ***************************************
2517 static void
powerButtonDownCallout(thread_call_param_t us,thread_call_param_t)2518 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2519 {
2520 /* Power button pressed during wake
2521 * Take a stackshot
2522 */
2523 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2524 ((IOPMrootDomain *)us)->takeStackshot(false);
2525 }
2526
2527 static void
powerButtonUpCallout(thread_call_param_t us,thread_call_param_t)2528 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2529 {
2530 /* Power button released.
2531 * Delete any stackshot data
2532 */
2533 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2534 ((IOPMrootDomain *)us)->deleteStackshot();
2535 }
2536 //*************************************************************************
2537 //
2538
2539 // MARK: -
2540 // MARK: System Sleep
2541
2542 //******************************************************************************
2543 // startIdleSleepTimer
2544 //
2545 //******************************************************************************
2546
2547 void
startIdleSleepTimer(uint32_t inMilliSeconds)2548 IOPMrootDomain::startIdleSleepTimer( uint32_t inMilliSeconds )
2549 {
2550 AbsoluteTime deadline;
2551
2552 ASSERT_GATED();
2553 if (gNoIdleFlag) {
2554 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2555 return;
2556 }
2557 if (inMilliSeconds) {
2558 if (inMilliSeconds < kMinimumTimeBeforeIdleSleep) {
2559 AbsoluteTime now;
2560 uint64_t nsec_since_wake;
2561 uint64_t msec_since_wake;
2562
2563 // Adjust idle timer so it will not expire until atleast kMinimumTimeBeforeIdleSleep milliseconds
2564 // after the most recent AP wake.
2565 clock_get_uptime(&now);
2566 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2567 absolutetime_to_nanoseconds(now, &nsec_since_wake);
2568 msec_since_wake = nsec_since_wake / NSEC_PER_MSEC;
2569
2570 if (msec_since_wake < kMinimumTimeBeforeIdleSleep) {
2571 uint32_t newIdleTimer = kMinimumTimeBeforeIdleSleep - (uint32_t)msec_since_wake;
2572
2573 // Ensure that our new idle timer is not less than inMilliSeconds,
2574 // as we should only be increasing the timer duration, not decreasing it
2575 if (newIdleTimer > inMilliSeconds) {
2576 DLOG("startIdleSleepTimer increasing timeout from %u to %u\n", inMilliSeconds, newIdleTimer);
2577 inMilliSeconds = newIdleTimer;
2578 }
2579 }
2580 }
2581 clock_interval_to_deadline(inMilliSeconds, kMillisecondScale, &deadline);
2582 thread_call_enter_delayed(extraSleepTimer, deadline);
2583 idleSleepTimerPending = true;
2584 } else {
2585 thread_call_enter(extraSleepTimer);
2586 }
2587 DLOG("idle timer set for %u milliseconds\n", inMilliSeconds);
2588 }
2589
2590 //******************************************************************************
2591 // cancelIdleSleepTimer
2592 //
2593 //******************************************************************************
2594
2595 void
cancelIdleSleepTimer(void)2596 IOPMrootDomain::cancelIdleSleepTimer( void )
2597 {
2598 ASSERT_GATED();
2599 if (idleSleepTimerPending) {
2600 DLOG("idle timer cancelled\n");
2601 thread_call_cancel(extraSleepTimer);
2602 idleSleepTimerPending = false;
2603
2604 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2605 AbsoluteTime now;
2606 clock_usec_t microsecs;
2607 clock_get_uptime(&now);
2608 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2609 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
2610 if (assertOnWakeReport) {
2611 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2612 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2613 }
2614 }
2615 }
2616 }
2617
2618 //******************************************************************************
2619 // idleSleepTimerExpired
2620 //
2621 //******************************************************************************
2622
2623 static void
idleSleepTimerExpired(thread_call_param_t us,thread_call_param_t)2624 idleSleepTimerExpired(
2625 thread_call_param_t us, thread_call_param_t )
2626 {
2627 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2628 }
2629
2630 //******************************************************************************
2631 // handleSleepTimerExpiration
2632 //
2633 // The time between the sleep idle timeout and the next longest one has elapsed.
2634 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2635 //******************************************************************************
2636
2637 void
handleSleepTimerExpiration(void)2638 IOPMrootDomain::handleSleepTimerExpiration( void )
2639 {
2640 if (!gIOPMWorkLoop->inGate()) {
2641 gIOPMWorkLoop->runAction(
2642 OSMemberFunctionCast(IOWorkLoop::Action, this,
2643 &IOPMrootDomain::handleSleepTimerExpiration),
2644 this);
2645 return;
2646 }
2647
2648 DLOG("sleep timer expired\n");
2649 ASSERT_GATED();
2650
2651 idleSleepTimerPending = false;
2652 setQuickSpinDownTimeout();
2653 adjustPowerState(true);
2654 }
2655
2656 //******************************************************************************
2657 // getTimeToIdleSleep
2658 //
2659 // Returns number of milliseconds left before going into idle sleep.
2660 // Caller has to make sure that idle sleep is allowed at the time of calling
2661 // this function
2662 //******************************************************************************
2663
2664 uint32_t
getTimeToIdleSleep(void)2665 IOPMrootDomain::getTimeToIdleSleep( void )
2666 {
2667 AbsoluteTime now, lastActivityTime;
2668 uint64_t nanos;
2669 uint32_t minutesSinceUserInactive = 0;
2670 uint32_t sleepDelay = 0;
2671
2672 if (!idleSleepEnabled) {
2673 return 0xffffffff;
2674 }
2675
2676 if (userActivityTime) {
2677 lastActivityTime = userActivityTime;
2678 } else {
2679 lastActivityTime = userBecameInactiveTime;
2680 }
2681
2682 // Ignore any lastActivityTime that predates the last system wake.
2683 // The goal is to avoid a sudden idle sleep right after a dark wake
2684 // due to sleepDelay=0 computed below. The alternative 60s minimum
2685 // timeout should be large enough to allow dark wake to complete,
2686 // at which point the idle timer will be promptly cancelled.
2687 clock_get_uptime(&now);
2688 if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) &&
2689 (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) {
2690 SUB_ABSOLUTETIME(&now, &lastActivityTime);
2691 absolutetime_to_nanoseconds(now, &nanos);
2692 minutesSinceUserInactive = nanos / (60000000000ULL);
2693
2694 if (minutesSinceUserInactive >= sleepSlider) {
2695 sleepDelay = 0;
2696 } else {
2697 sleepDelay = sleepSlider - minutesSinceUserInactive;
2698 }
2699 } else {
2700 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2701 lastActivityTime, now, gIOLastWakeAbsTime);
2702 sleepDelay = sleepSlider;
2703 }
2704
2705 DLOG("user inactive %u min, time to idle sleep %u min\n",
2706 minutesSinceUserInactive, sleepDelay);
2707
2708 return sleepDelay * 60 * 1000;
2709 }
2710
2711 //******************************************************************************
2712 // setQuickSpinDownTimeout
2713 //
2714 //******************************************************************************
2715
2716 void
setQuickSpinDownTimeout(void)2717 IOPMrootDomain::setQuickSpinDownTimeout( void )
2718 {
2719 ASSERT_GATED();
2720 setAggressiveness(
2721 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2722 }
2723
2724 //******************************************************************************
2725 // restoreUserSpinDownTimeout
2726 //
2727 //******************************************************************************
2728
2729 void
restoreUserSpinDownTimeout(void)2730 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2731 {
2732 ASSERT_GATED();
2733 setAggressiveness(
2734 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2735 }
2736
2737 //******************************************************************************
2738 // sleepSystem
2739 //
2740 //******************************************************************************
2741
2742 /* public */
2743 IOReturn
sleepSystem(void)2744 IOPMrootDomain::sleepSystem( void )
2745 {
2746 return sleepSystemOptions(NULL);
2747 }
2748
2749 /* private */
2750 IOReturn
sleepSystemOptions(OSDictionary * options)2751 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2752 {
2753 OSObject *obj = NULL;
2754 OSString *reason = NULL;
2755 /* sleepSystem is a public function, and may be called by any kernel driver.
2756 * And that's bad - drivers should sleep the system by calling
2757 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2758 *
2759 * Note that user space app calls to IOPMSleepSystem() will also travel
2760 * this code path and thus be correctly identified as software sleeps.
2761 */
2762
2763 if (options && options->getObject("OSSwitch")) {
2764 // Log specific sleep cause for OS Switch hibernation
2765 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2766 }
2767
2768 if (options && (obj = options->getObject("Sleep Reason"))) {
2769 reason = OSDynamicCast(OSString, obj);
2770 if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2771 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2772 }
2773 if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2774 return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2775 }
2776 }
2777
2778 return privateSleepSystem( kIOPMSleepReasonSoftware);
2779 }
2780
2781 /* private */
2782 IOReturn
privateSleepSystem(uint32_t sleepReason)2783 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2784 {
2785 /* Called from both gated and non-gated context */
2786
2787 if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2788 return kIOReturnNotPermitted;
2789 }
2790
2791 pmPowerStateQueue->submitPowerEvent(
2792 kPowerEventPolicyStimulus,
2793 (void *) kStimulusDemandSystemSleep,
2794 sleepReason);
2795
2796 return kIOReturnSuccess;
2797 }
2798
2799 //******************************************************************************
2800 // powerChangeDone
2801 //
2802 // This overrides powerChangeDone in IOService.
2803 //******************************************************************************
2804 void
powerChangeDone(unsigned long previousPowerState)2805 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2806 {
2807 #if !__i386__ && !__x86_64__
2808 uint64_t timeSinceReset = 0;
2809 #endif
2810 uint64_t now;
2811 unsigned long newState;
2812 clock_sec_t secs;
2813 clock_usec_t microsecs;
2814 uint32_t lastDebugWakeSeconds;
2815 clock_sec_t adjWakeTime;
2816 IOPMCalendarStruct nowCalendar;
2817
2818 ASSERT_GATED();
2819 newState = getPowerState();
2820 DLOG("PowerChangeDone: %s->%s\n",
2821 getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2822
2823 if (previousPowerState == newState) {
2824 return;
2825 }
2826
2827 notifierThread = current_thread();
2828 switch (getPowerState()) {
2829 case SLEEP_STATE: {
2830 if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2831 secs = 0;
2832 microsecs = 0;
2833 PEGetUTCTimeOfDay(&secs, µsecs);
2834
2835 adjWakeTime = 0;
2836 if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) {
2837 IOLog("use _calendarWakeAlarmUTC\n");
2838 adjWakeTime = _calendarWakeAlarmUTC;
2839 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
2840 IOLog("accelerate _aotWakeTime for exit\n");
2841 adjWakeTime = secs;
2842 } else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2843 IOLog("accelerate _aotWakeTime for assertion\n");
2844 adjWakeTime = secs;
2845 }
2846 if (adjWakeTime) {
2847 IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2848 }
2849
2850 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2851 IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2852
2853 IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2854 assert(kIOReturnSuccess == ret);
2855 }
2856 if (_aotLastWakeTime) {
2857 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
2858 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
2859 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
2860 gWakeReasonString,
2861 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2862 }
2863 }
2864 _aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2865 if (_aotTimerScheduled) {
2866 _aotTimerES->cancelTimeout();
2867 _aotTimerScheduled = false;
2868 }
2869 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2870
2871 // re-enable this timer for next sleep
2872 cancelIdleSleepTimer();
2873
2874 if (clamshellExists) {
2875 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
2876 if (gClamshellFlags & kClamshell_WAR_58009435) {
2877 // Disable clamshell sleep until system has completed full wake.
2878 // This prevents a system sleep request (due to a clamshell close)
2879 // from being queued until the end of system full wake - even if
2880 // other clamshell disable bits outside of our control is wrong.
2881 setClamShellSleepDisable(true, kClamshellSleepDisableInternal);
2882 }
2883 #endif
2884
2885 // Log the last known clamshell state before system sleep
2886 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
2887 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask,
2888 desktopMode, acAdaptorConnected);
2889 }
2890
2891 clock_get_calendar_absolute_and_microtime(&secs, µsecs, &now);
2892 logtime(secs);
2893 gIOLastSleepTime.tv_sec = secs;
2894 gIOLastSleepTime.tv_usec = microsecs;
2895 if (!_aotLastWakeTime) {
2896 gIOLastUserSleepTime = gIOLastSleepTime;
2897 }
2898
2899 gIOLastWakeTime.tv_sec = 0;
2900 gIOLastWakeTime.tv_usec = 0;
2901 gIOLastSleepAbsTime = now;
2902
2903 if (wake2DarkwakeDelay && sleepDelaysReport) {
2904 clock_sec_t wake2DarkwakeSecs, darkwake2SleepSecs;
2905 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2906
2907 SUB_ABSOLUTETIME(&now, &ts_sleepStart);
2908 absolutetime_to_microtime(now, &darkwake2SleepSecs, µsecs);
2909 absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, µsecs);
2910 HISTREPORT_TALLYVALUE(sleepDelaysReport,
2911 (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
2912
2913 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
2914 wake2DarkwakeDelay = 0;
2915 }
2916 #if HIBERNATION
2917 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2918 #if (DEVELOPMENT || DEBUG)
2919 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2920 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2921 "System State",
2922 gIOHibernateState ? "Enter Hibernate" : "Enter Sleep"
2923 );
2924 #endif /* DEVELOPMENT || DEBUG */
2925 IOHibernateSystemHasSlept();
2926
2927 evaluateSystemSleepPolicyFinal();
2928 #else
2929 LOG("System Sleep\n");
2930 #if (DEVELOPMENT || DEBUG)
2931 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2932 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2933 "System State", "Enter Sleep");
2934 #endif /* DEVELOPMENT || DEBUG */
2935 #endif
2936 if (thermalWarningState) {
2937 OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
2938 if (event) {
2939 systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
2940 }
2941 }
2942 assertOnWakeSecs = 0;
2943 lowBatteryCondition = false;
2944 thermalEmergencyState = false;
2945
2946 #if DEVELOPMENT || DEBUG
2947 extern int g_should_log_clock_adjustments;
2948 if (g_should_log_clock_adjustments) {
2949 clock_sec_t secs = 0;
2950 clock_usec_t microsecs = 0;
2951 uint64_t now_b = mach_absolute_time();
2952
2953 secs = 0;
2954 microsecs = 0;
2955 PEGetUTCTimeOfDay(&secs, µsecs);
2956
2957 uint64_t now_a = mach_absolute_time();
2958 os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2959 __func__, (unsigned long)secs, microsecs, now_b, now_a);
2960 }
2961 #endif
2962
2963 getPlatform()->sleepKernel();
2964
2965 // The CPU(s) are off at this point,
2966 // Code will resume execution here upon wake.
2967
2968 clock_get_uptime(&gIOLastWakeAbsTime);
2969 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
2970 #if DEVELOPMENT || DEBUG
2971 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2972 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2973 "System State", "Waking Up"
2974 );
2975 #endif /* DEVELOPMENT || DEBUG */
2976 _highestCapability = 0;
2977
2978 #if HIBERNATION
2979 IOHibernateSystemWake();
2980 #endif
2981
2982 // sleep transition complete
2983 gSleepOrShutdownPending = 0;
2984
2985 // trip the reset of the calendar clock
2986 clock_wakeup_calendar();
2987 clock_get_calendar_microtime(&secs, µsecs);
2988 gIOLastWakeTime.tv_sec = secs;
2989 gIOLastWakeTime.tv_usec = microsecs;
2990
2991 // aot
2992 if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
2993 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
2994 secs = 0;
2995 microsecs = 0;
2996 PEGetUTCTimeOfDay(&secs, µsecs);
2997 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2998 IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2999 _aotMetrics->sleepCount++;
3000 _aotLastWakeTime = gIOLastWakeAbsTime;
3001 if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
3002 _aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
3003 = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
3004 _aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
3005 = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
3006 }
3007
3008 if (_aotTestTime) {
3009 if (_aotWakeTimeUTC <= secs) {
3010 _aotTestTime = _aotTestTime + _aotTestInterval;
3011 }
3012 setWakeTime(_aotTestTime);
3013 }
3014 }
3015
3016 #if HIBERNATION
3017 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
3018 #endif
3019
3020 lastSleepReason = 0;
3021
3022 lastDebugWakeSeconds = _debugWakeSeconds;
3023 _debugWakeSeconds = 0;
3024 _scheduledAlarmMask = 0;
3025 _nextScheduledAlarmType = NULL;
3026
3027 darkWakeExit = false;
3028 darkWakePowerClamped = false;
3029 darkWakePostTickle = false;
3030 darkWakeHibernateError = false;
3031 darkWakeToSleepASAP = true;
3032 darkWakeLogClamp = true;
3033 sleepTimerMaintenance = false;
3034 sleepToStandby = false;
3035 wranglerTickled = false;
3036 userWasActive = false;
3037 isRTCAlarmWake = false;
3038 clamshellIgnoreClose = false;
3039 fullWakeReason = kFullWakeReasonNone;
3040 idleSleepRevertible = true;
3041
3042 #if defined(__i386__) || defined(__x86_64__)
3043 kdebugTrace(kPMLogSystemWake, 0, 0, 0);
3044
3045 OSSharedPtr<OSObject> wakeTypeProp = copyProperty(kIOPMRootDomainWakeTypeKey);
3046 OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey);
3047 OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get());
3048 OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get());
3049
3050 if (wakeReason && (wakeReason->getLength() >= 2) &&
3051 gWakeReasonString[0] == '\0') {
3052 WAKEEVENT_LOCK();
3053 // Until the platform driver can claim its wake reasons
3054 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
3055 sizeof(gWakeReasonString));
3056 if (!gWakeReasonSysctlRegistered) {
3057 gWakeReasonSysctlRegistered = true;
3058 }
3059 WAKEEVENT_UNLOCK();
3060 }
3061
3062 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
3063 lowBatteryCondition = true;
3064 darkWakeMaintenance = true;
3065 } else {
3066 #if HIBERNATION
3067 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3068 OSNumber * hibOptions = OSDynamicCast( OSNumber, hibOptionsProp.get());
3069 if (hibernateAborted || ((hibOptions &&
3070 !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
3071 // Hibernate aborted, or EFI brought up graphics
3072 darkWakeExit = true;
3073 if (hibernateAborted) {
3074 DLOG("Hibernation aborted\n");
3075 } else {
3076 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
3077 }
3078 } else
3079 #endif
3080 if (wakeType && (
3081 wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
3082 wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
3083 // User wake or RTC alarm
3084 darkWakeExit = true;
3085 if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
3086 isRTCAlarmWake = true;
3087 }
3088 } else if (wakeType &&
3089 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
3090 // SMC standby timer trumps SleepX
3091 darkWakeMaintenance = true;
3092 sleepTimerMaintenance = true;
3093 } else if ((lastDebugWakeSeconds != 0) &&
3094 ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
3095 // SleepX before maintenance
3096 darkWakeExit = true;
3097 } else if (wakeType &&
3098 wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
3099 darkWakeMaintenance = true;
3100 } else if (wakeType &&
3101 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
3102 darkWakeMaintenance = true;
3103 darkWakeSleepService = true;
3104 #if HIBERNATION
3105 if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3106 sleepToStandby = true;
3107 }
3108 #endif
3109 } else if (wakeType &&
3110 wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3111 darkWakeMaintenance = true;
3112 darkWakeHibernateError = true;
3113 } else {
3114 // Unidentified wake source, resume to full wake if debug
3115 // alarm is pending.
3116
3117 if (lastDebugWakeSeconds &&
3118 (!wakeReason || wakeReason->isEqualTo(""))) {
3119 darkWakeExit = true;
3120 }
3121 }
3122 }
3123
3124 if (darkWakeExit) {
3125 darkWakeToSleepASAP = false;
3126 fullWakeReason = kFullWakeReasonLocalUser;
3127 reportUserInput();
3128 } else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
3129 handleSetDisplayPowerOn(true);
3130 } else if (!darkWakeMaintenance) {
3131 // Early/late tickle for non-maintenance wake.
3132 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) {
3133 darkWakePostTickle = true;
3134 }
3135 }
3136 #else /* !__i386__ && !__x86_64__ */
3137 timeSinceReset = ml_get_time_since_reset();
3138 kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3139
3140 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) {
3141 wranglerTickled = true;
3142 fullWakeReason = kFullWakeReasonLocalUser;
3143 requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3144 } else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
3145 isRTCAlarmWake = true;
3146 fullWakeReason = kFullWakeReasonLocalUser;
3147 requestUserActive(this, "RTC debug alarm");
3148 } else {
3149 #if HIBERNATION
3150 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3151 OSNumber * hibOptions = OSDynamicCast(OSNumber, hibOptionsProp.get());
3152 if (hibOptions && !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)) {
3153 fullWakeReason = kFullWakeReasonLocalUser;
3154 requestUserActive(this, "hibernate user wake");
3155 }
3156 #endif
3157 }
3158
3159 // stay awake for at least 30 seconds
3160 startIdleSleepTimer(30 * 1000);
3161 #endif
3162 sleepCnt++;
3163
3164 thread_call_enter(updateConsoleUsersEntry);
3165
3166 // Skip AOT_STATE if we are waking up from an RTC timer.
3167 // This check needs to be done after the epoch change is processed
3168 // and before the changePowerStateWithTagToPriv() call below.
3169 WAKEEVENT_LOCK();
3170 aotShouldExit(false);
3171 WAKEEVENT_UNLOCK();
3172
3173 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
3174 break;
3175 }
3176 #if !__i386__ && !__x86_64__
3177 case ON_STATE:
3178 case AOT_STATE:
3179 {
3180 DLOG("Force re-evaluating aggressiveness\n");
3181 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3182 pmPowerStateQueue->submitPowerEvent(
3183 kPowerEventPolicyStimulus,
3184 (void *) kStimulusNoIdleSleepPreventers );
3185
3186 // After changing to ON_STATE, invalidate any previously queued
3187 // request to change to a state less than ON_STATE. This isn't
3188 // necessary for AOT_STATE or if the device has only one running
3189 // state since the changePowerStateToPriv() issued at the tail
3190 // end of SLEEP_STATE case should take care of that.
3191 if (getPowerState() == ON_STATE) {
3192 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake);
3193 }
3194 break;
3195 }
3196 #endif /* !__i386__ && !__x86_64__ */
3197 }
3198 notifierThread = NULL;
3199 }
3200
3201 //******************************************************************************
3202 // requestPowerDomainState
3203 //
3204 // Extend implementation in IOService. Running on PM work loop thread.
3205 //******************************************************************************
3206
3207 IOReturn
requestPowerDomainState(IOPMPowerFlags childDesire,IOPowerConnection * childConnection,unsigned long specification)3208 IOPMrootDomain::requestPowerDomainState(
3209 IOPMPowerFlags childDesire,
3210 IOPowerConnection * childConnection,
3211 unsigned long specification )
3212 {
3213 // Idle and system sleep prevention flags affects driver desire.
3214 // Children desire are irrelevant so they are cleared.
3215
3216 return super::requestPowerDomainState(0, childConnection, specification);
3217 }
3218
3219
3220 static void
makeSleepPreventersListLog(const OSSharedPtr<OSSet> & preventers,char * buf,size_t buf_size)3221 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3222 {
3223 if (!preventers->getCount()) {
3224 return;
3225 }
3226
3227 char *buf_iter = buf + strlen(buf);
3228 char *buf_end = buf + buf_size;
3229
3230 OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3231 OSObject *obj = NULL;
3232
3233 while ((obj = iterator->getNextObject())) {
3234 IOService *srv = OSDynamicCast(IOService, obj);
3235 if (buf_iter < buf_end) {
3236 buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName());
3237 } else {
3238 DLOG("Print buffer exhausted for sleep preventers list\n");
3239 break;
3240 }
3241 }
3242 }
3243
3244 //******************************************************************************
3245 // updatePreventIdleSleepList
3246 //
3247 // Called by IOService on PM work loop.
3248 // Returns true if PM policy recognized the driver's desire to prevent idle
3249 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3250 //******************************************************************************
3251
3252 bool
updatePreventIdleSleepList(IOService * service,bool addNotRemove)3253 IOPMrootDomain::updatePreventIdleSleepList(
3254 IOService * service, bool addNotRemove)
3255 {
3256 unsigned int oldCount;
3257
3258 oldCount = idleSleepPreventersCount();
3259 return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3260 }
3261
3262 bool
updatePreventIdleSleepListInternal(IOService * service,bool addNotRemove,unsigned int oldCount)3263 IOPMrootDomain::updatePreventIdleSleepListInternal(
3264 IOService * service, bool addNotRemove, unsigned int oldCount)
3265 {
3266 unsigned int newCount;
3267
3268 ASSERT_GATED();
3269
3270 #if defined(XNU_TARGET_OS_OSX)
3271 // Only the display wrangler and no-idle-sleep kernel assertions
3272 // can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3273 // reported by drivers in their power state table is ignored.
3274 if (service && (service != wrangler) && (service != this)) {
3275 return false;
3276 }
3277 #endif
3278
3279 if (service) {
3280 if (addNotRemove) {
3281 preventIdleSleepList->setObject(service);
3282 DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3283 service->getName(), preventIdleSleepList->getCount());
3284 } else if (preventIdleSleepList->member(service)) {
3285 preventIdleSleepList->removeObject(service);
3286 DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3287 service->getName(), preventIdleSleepList->getCount());
3288 }
3289
3290 if (preventIdleSleepList->getCount()) {
3291 char buf[256] = "Idle Sleep Preventers:";
3292 makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3293 DLOG("%s\n", buf);
3294 }
3295 }
3296
3297 newCount = idleSleepPreventersCount();
3298
3299 if ((oldCount == 0) && (newCount != 0)) {
3300 // Driver added to empty prevent list.
3301 // Update the driver desire to prevent idle sleep.
3302 // Driver desire does not prevent demand sleep.
3303
3304 changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent);
3305 } else if ((oldCount != 0) && (newCount == 0)) {
3306 // Last driver removed from prevent list.
3307 // Drop the driver clamp to allow idle sleep.
3308
3309 changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3310 evaluatePolicy( kStimulusNoIdleSleepPreventers );
3311 }
3312 messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3313 &newCount, sizeof(newCount));
3314
3315 #if defined(XNU_TARGET_OS_OSX)
3316 if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
3317 DLOG("Cannot cancel idle sleep\n");
3318 return false; // do not idle-cancel
3319 }
3320 #endif
3321
3322 return true;
3323 }
3324
3325 //******************************************************************************
3326 // startSpinDump
3327 //******************************************************************************
3328
3329 void
startSpinDump(uint32_t spindumpKind)3330 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3331 {
3332 messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3333 }
3334
3335 //******************************************************************************
3336 // preventSystemSleepListUpdate
3337 //
3338 // Called by IOService on PM work loop.
3339 //******************************************************************************
3340
3341 void
updatePreventSystemSleepList(IOService * service,bool addNotRemove)3342 IOPMrootDomain::updatePreventSystemSleepList(
3343 IOService * service, bool addNotRemove )
3344 {
3345 unsigned int oldCount, newCount;
3346
3347 ASSERT_GATED();
3348 if (this == service) {
3349 return;
3350 }
3351
3352 oldCount = preventSystemSleepList->getCount();
3353 if (addNotRemove) {
3354 preventSystemSleepList->setObject(service);
3355 DLOG("Added %s to system sleep preventers list (Total %u)\n",
3356 service->getName(), preventSystemSleepList->getCount());
3357 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
3358 AbsoluteTime now;
3359 clock_usec_t microsecs;
3360 clock_get_uptime(&now);
3361 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3362 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
3363 if (assertOnWakeReport) {
3364 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3365 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3366 }
3367 }
3368 } else if (preventSystemSleepList->member(service)) {
3369 preventSystemSleepList->removeObject(service);
3370 DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3371 service->getName(), preventSystemSleepList->getCount());
3372
3373 if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
3374 // Lost all system sleep preventers.
3375 // Send stimulus if system sleep was blocked, and is in dark wake.
3376 evaluatePolicy( kStimulusDarkWakeEvaluate );
3377 }
3378 }
3379
3380 newCount = preventSystemSleepList->getCount();
3381 if (newCount) {
3382 char buf[256] = "System Sleep Preventers:";
3383 makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3384 DLOG("%s\n", buf);
3385 }
3386
3387 messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3388 &newCount, sizeof(newCount));
3389 }
3390
3391 void
copySleepPreventersList(OSArray ** idleSleepList,OSArray ** systemSleepList)3392 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3393 {
3394 OSSharedPtr<OSCollectionIterator> iterator;
3395 OSObject *object = NULL;
3396 OSSharedPtr<OSArray> array;
3397
3398 if (!gIOPMWorkLoop->inGate()) {
3399 gIOPMWorkLoop->runAction(
3400 OSMemberFunctionCast(IOWorkLoop::Action, this,
3401 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3402 this, (void *)idleSleepList, (void *)systemSleepList);
3403 return;
3404 }
3405
3406 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3407 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3408 array = OSArray::withCapacity(5);
3409
3410 if (iterator && array) {
3411 while ((object = iterator->getNextObject())) {
3412 IOService *service = OSDynamicCast(IOService, object);
3413 if (service) {
3414 OSSharedPtr<const OSSymbol> name = service->copyName();
3415 if (name) {
3416 array->setObject(name.get());
3417 }
3418 }
3419 }
3420 }
3421 *idleSleepList = array.detach();
3422 }
3423
3424 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3425 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3426 array = OSArray::withCapacity(5);
3427
3428 if (iterator && array) {
3429 while ((object = iterator->getNextObject())) {
3430 IOService *service = OSDynamicCast(IOService, object);
3431 if (service) {
3432 OSSharedPtr<const OSSymbol> name = service->copyName();
3433 if (name) {
3434 array->setObject(name.get());
3435 }
3436 }
3437 }
3438 }
3439 *systemSleepList = array.detach();
3440 }
3441 }
3442
3443 void
copySleepPreventersListWithID(OSArray ** idleSleepList,OSArray ** systemSleepList)3444 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3445 {
3446 OSSharedPtr<OSCollectionIterator> iterator;
3447 OSObject *object = NULL;
3448 OSSharedPtr<OSArray> array;
3449
3450 if (!gIOPMWorkLoop->inGate()) {
3451 gIOPMWorkLoop->runAction(
3452 OSMemberFunctionCast(IOWorkLoop::Action, this,
3453 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3454 this, (void *)idleSleepList, (void *)systemSleepList);
3455 return;
3456 }
3457
3458 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3459 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3460 array = OSArray::withCapacity(5);
3461
3462 if (iterator && array) {
3463 while ((object = iterator->getNextObject())) {
3464 IOService *service = OSDynamicCast(IOService, object);
3465 if (service) {
3466 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3467 OSSharedPtr<const OSSymbol> name = service->copyName();
3468 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3469 if (dict && name && id) {
3470 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3471 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3472 array->setObject(dict.get());
3473 }
3474 }
3475 }
3476 }
3477 *idleSleepList = array.detach();
3478 }
3479
3480 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3481 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3482 array = OSArray::withCapacity(5);
3483
3484 if (iterator && array) {
3485 while ((object = iterator->getNextObject())) {
3486 IOService *service = OSDynamicCast(IOService, object);
3487 if (service) {
3488 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3489 OSSharedPtr<const OSSymbol> name = service->copyName();
3490 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3491 if (dict && name && id) {
3492 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3493 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3494 array->setObject(dict.get());
3495 }
3496 }
3497 }
3498 }
3499 *systemSleepList = array.detach();
3500 }
3501 }
3502
3503 //******************************************************************************
3504 // tellChangeDown
3505 //
3506 // Override the superclass implementation to send a different message type.
3507 //******************************************************************************
3508
3509 bool
tellChangeDown(unsigned long stateNum)3510 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3511 {
3512 DLOG("tellChangeDown %s->%s\n",
3513 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3514
3515 if (SLEEP_STATE == stateNum) {
3516 // Legacy apps were already told in the full->dark transition
3517 if (!ignoreTellChangeDown) {
3518 tracePoint( kIOPMTracePointSleepApplications );
3519 } else {
3520 tracePoint( kIOPMTracePointSleepPriorityClients );
3521 }
3522 }
3523
3524 if (!ignoreTellChangeDown) {
3525 userActivityAtSleep = userActivityCount;
3526 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3527
3528 if (SLEEP_STATE == stateNum) {
3529 hibernateAborted = false;
3530
3531 // Direct callout into OSKext so it can disable kext unloads
3532 // during sleep/wake to prevent deadlocks.
3533 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3534
3535 IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3536
3537 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3538 // But tellClientsWithResponse() must be called for both.
3539 ignoreTellChangeDown = true;
3540 }
3541 }
3542
3543 return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3544 }
3545
3546 //******************************************************************************
3547 // askChangeDown
3548 //
3549 // Override the superclass implementation to send a different message type.
3550 // This must be idle sleep since we don't ask during any other power change.
3551 //******************************************************************************
3552
3553 bool
askChangeDown(unsigned long stateNum)3554 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3555 {
3556 DLOG("askChangeDown %s->%s\n",
3557 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3558
3559 // Don't log for dark wake entry
3560 if (kSystemTransitionSleep == _systemTransitionType) {
3561 tracePoint( kIOPMTracePointSleepApplications );
3562 }
3563
3564 return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3565 }
3566
3567 //******************************************************************************
3568 // askChangeDownDone
3569 //
3570 // An opportunity for root domain to cancel the power transition,
3571 // possibily due to an assertion created by powerd in response to
3572 // kIOMessageCanSystemSleep.
3573 //
3574 // Idle sleep:
3575 // full -> dark wake transition
3576 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3577 // 2. askChangeDownDone()
3578 // dark -> sleep transition
3579 // 1. Notify powerd with kIOMessageCanSystemSleep
3580 // 2. askChangeDownDone()
3581 //
3582 // Demand sleep:
3583 // full -> dark wake transition
3584 // 1. Notify powerd with kIOMessageCanSystemSleep
3585 // 2. askChangeDownDone()
3586 // dark -> sleep transition
3587 // 1. Notify powerd with kIOMessageCanSystemSleep
3588 // 2. askChangeDownDone()
3589 //******************************************************************************
3590
3591 void
askChangeDownDone(IOPMPowerChangeFlags * inOutChangeFlags,bool * cancel)3592 IOPMrootDomain::askChangeDownDone(
3593 IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3594 {
3595 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3596 *inOutChangeFlags, *cancel,
3597 _systemTransitionType,
3598 _currentCapability, _pendingCapability);
3599
3600 if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
3601 // Dark->Sleep transition.
3602 // Check if there are any deny sleep assertions.
3603 // lastSleepReason already set by handleOurPowerChangeStart()
3604
3605 if (!checkSystemCanSleep(lastSleepReason)) {
3606 // Cancel dark wake to sleep transition.
3607 // Must re-scan assertions upon entering dark wake.
3608
3609 *cancel = true;
3610 DLOG("cancel dark->sleep\n");
3611 }
3612 if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3613 uint64_t now = mach_continuous_time();
3614 if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3615 && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3616 *cancel = true;
3617 IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3618 }
3619 }
3620 }
3621 }
3622
3623 //******************************************************************************
3624 // systemDidNotSleep
3625 //
3626 // Work common to both canceled or aborted sleep.
3627 //******************************************************************************
3628
3629 void
systemDidNotSleep(void)3630 IOPMrootDomain::systemDidNotSleep( void )
3631 {
3632 // reset console lock state
3633 thread_call_enter(updateConsoleUsersEntry);
3634
3635 if (idleSleepEnabled) {
3636 if (!wrangler) {
3637 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3638 startIdleSleepTimer(kIdleSleepRetryInterval);
3639 #else
3640 startIdleSleepTimer(idleMilliSeconds);
3641 #endif
3642 } else if (!userIsActive) {
3643 // Manually start the idle sleep timer besides waiting for
3644 // the user to become inactive.
3645 startIdleSleepTimer(kIdleSleepRetryInterval);
3646 }
3647 }
3648
3649 preventTransitionToUserActive(false);
3650 IOService::setAdvisoryTickleEnable( true );
3651 idleSleepRevertible = true;
3652
3653 // After idle revert and cancel, send a did-change message to powerd
3654 // to balance the previous will-change message. Kernel clients do not
3655 // need this since sleep cannot be canceled once they are notified.
3656
3657 if (toldPowerdCapWillChange && systemCapabilityNotifier &&
3658 (_pendingCapability != _currentCapability) &&
3659 ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
3660 // Differs from a real capability gain change where notifyRef != 0,
3661 // but it is zero here since no response is expected.
3662
3663 IOPMSystemCapabilityChangeParameters params;
3664
3665 bzero(¶ms, sizeof(params));
3666 params.fromCapabilities = _pendingCapability;
3667 params.toCapabilities = _currentCapability;
3668 params.changeFlags = kIOPMSystemCapabilityDidChange;
3669
3670 DLOG("MESG cap %x->%x did change\n",
3671 params.fromCapabilities, params.toCapabilities);
3672 messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3673 ¶ms, sizeof(params));
3674 }
3675 }
3676
3677 //******************************************************************************
3678 // tellNoChangeDown
3679 //
3680 // Notify registered applications and kernel clients that we are not dropping
3681 // power.
3682 //
3683 // We override the superclass implementation so we can send a different message
3684 // type to the client or application being notified.
3685 //
3686 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3687 //******************************************************************************
3688
3689 void
tellNoChangeDown(unsigned long stateNum)3690 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3691 {
3692 DLOG("tellNoChangeDown %s->%s\n",
3693 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3694
3695 // Sleep canceled, clear the sleep trace point.
3696 tracePoint(kIOPMTracePointSystemUp);
3697
3698 systemDidNotSleep();
3699 return tellClients( kIOMessageSystemWillNotSleep );
3700 }
3701
3702 //******************************************************************************
3703 // tellChangeUp
3704 //
3705 // Notify registered applications and kernel clients that we are raising power.
3706 //
3707 // We override the superclass implementation so we can send a different message
3708 // type to the client or application being notified.
3709 //******************************************************************************
3710
3711 void
tellChangeUp(unsigned long stateNum)3712 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3713 {
3714 DLOG("tellChangeUp %s->%s\n",
3715 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3716
3717 ignoreTellChangeDown = false;
3718
3719 if (stateNum == ON_STATE) {
3720 // Direct callout into OSKext so it can disable kext unloads
3721 // during sleep/wake to prevent deadlocks.
3722 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3723
3724 // Notify platform that sleep was cancelled or resumed.
3725 getPlatform()->callPlatformFunction(
3726 sleepMessagePEFunction.get(), false,
3727 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3728 NULL, NULL, NULL);
3729
3730 if (getPowerState() == ON_STATE) {
3731 // Sleep was cancelled by idle cancel or revert
3732 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
3733 // rdar://problem/50363791
3734 // If system is in dark wake and sleep is cancelled, do not
3735 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3736 // priority clients. They haven't yet seen a SystemWillSleep
3737 // message before the cancellation. So make sure the kernel
3738 // client bit is cleared in _systemMessageClientMask before
3739 // invoking the tellClients() below. This bit may have been
3740 // set by handleOurPowerChangeStart() anticipating a successful
3741 // sleep and setting the filter mask ahead of time allows the
3742 // SystemWillSleep message to go through.
3743 _systemMessageClientMask &= ~kSystemMessageClientKernel;
3744 }
3745
3746 systemDidNotSleep();
3747 tellClients( kIOMessageSystemWillPowerOn );
3748 }
3749
3750 tracePoint( kIOPMTracePointWakeApplications );
3751 tellClients( kIOMessageSystemHasPoweredOn );
3752 } else if (stateNum == AOT_STATE) {
3753 if (getPowerState() == AOT_STATE) {
3754 // Sleep was cancelled by idle cancel or revert
3755 startIdleSleepTimer(idleMilliSeconds);
3756 }
3757 }
3758 }
3759
3760 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3761 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3762 ((params)->fromCapabilities & (flag)) && \
3763 (((params)->toCapabilities & (flag)) == 0))
3764
3765 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3766 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3767 ((params)->toCapabilities & (flag)) && \
3768 (((params)->fromCapabilities & (flag)) == 0))
3769
3770 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3771 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3772 ((params)->fromCapabilities & (flag)) && \
3773 (((params)->toCapabilities & (flag)) == 0))
3774
3775 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3776 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3777 ((params)->toCapabilities & (flag)) && \
3778 (((params)->fromCapabilities & (flag)) == 0))
3779
3780 //******************************************************************************
3781 // sysPowerDownHandler
3782 //
3783 // Perform a vfs sync before system sleep.
3784 //******************************************************************************
3785
3786 IOReturn
sysPowerDownHandler(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgs,vm_size_t argSize)3787 IOPMrootDomain::sysPowerDownHandler(
3788 void * target, void * refCon,
3789 UInt32 messageType, IOService * service,
3790 void * messageArgs, vm_size_t argSize )
3791 {
3792 static UInt32 lastSystemMessageType = 0;
3793 IOReturn ret = 0;
3794
3795 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3796
3797 // rdar://problem/50363791
3798 // Sanity check to make sure the SystemWill/Has message types are
3799 // received in the expected order for all kernel priority clients.
3800 if (messageType == kIOMessageSystemWillSleep ||
3801 messageType == kIOMessageSystemWillPowerOn ||
3802 messageType == kIOMessageSystemHasPoweredOn) {
3803 switch (messageType) {
3804 case kIOMessageSystemWillPowerOn:
3805 assert(lastSystemMessageType == kIOMessageSystemWillSleep);
3806 break;
3807 case kIOMessageSystemHasPoweredOn:
3808 assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3809 break;
3810 }
3811
3812 lastSystemMessageType = messageType;
3813 }
3814
3815 if (!gRootDomain) {
3816 return kIOReturnUnsupported;
3817 }
3818
3819 if (messageType == kIOMessageSystemCapabilityChange) {
3820 IOPMSystemCapabilityChangeParameters * params =
3821 (IOPMSystemCapabilityChangeParameters *) messageArgs;
3822
3823 // Interested applications have been notified of an impending power
3824 // change and have acked (when applicable).
3825 // This is our chance to save whatever state we can before powering
3826 // down.
3827 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3828 // via callout
3829
3830 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3831 params->fromCapabilities, params->toCapabilities,
3832 params->changeFlags);
3833
3834 if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3835 // We will ack within 20 seconds
3836 params->maxWaitForReply = 20 * 1000 * 1000;
3837
3838 #if HIBERNATION
3839 gRootDomain->evaluateSystemSleepPolicyEarly();
3840
3841 // add in time we could spend freeing pages
3842 if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3843 params->maxWaitForReply = kCapabilityClientMaxWait;
3844 }
3845 DLOG("sysPowerDownHandler max wait %d s\n",
3846 (int) (params->maxWaitForReply / 1000 / 1000));
3847 #endif
3848
3849 // Notify platform that sleep has begun, after the early
3850 // sleep policy evaluation.
3851 getPlatform()->callPlatformFunction(
3852 sleepMessagePEFunction.get(), false,
3853 (void *)(uintptr_t) kIOMessageSystemWillSleep,
3854 NULL, NULL, NULL);
3855
3856 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3857 // Purposely delay the ack and hope that shutdown occurs quickly.
3858 // Another option is not to schedule the thread and wait for
3859 // ack timeout...
3860 AbsoluteTime deadline;
3861 clock_interval_to_deadline( 30, kSecondScale, &deadline );
3862 thread_call_enter1_delayed(
3863 gRootDomain->diskSyncCalloutEntry,
3864 (thread_call_param_t)(uintptr_t) params->notifyRef,
3865 deadline );
3866 } else {
3867 thread_call_enter1(
3868 gRootDomain->diskSyncCalloutEntry,
3869 (thread_call_param_t)(uintptr_t) params->notifyRef);
3870 }
3871 }
3872 #if HIBERNATION
3873 else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
3874 // We will ack within 110 seconds
3875 params->maxWaitForReply = 110 * 1000 * 1000;
3876
3877 thread_call_enter1(
3878 gRootDomain->diskSyncCalloutEntry,
3879 (thread_call_param_t)(uintptr_t) params->notifyRef);
3880 }
3881 #endif
3882 ret = kIOReturnSuccess;
3883 }
3884
3885 return ret;
3886 }
3887
3888 //******************************************************************************
3889 // handleQueueSleepWakeUUID
3890 //
3891 // Called from IOPMrootDomain when we're initiating a sleep,
3892 // or indirectly from PM configd when PM decides to clear the UUID.
3893 // PM clears the UUID several minutes after successful wake from sleep,
3894 // so that we might associate App spindumps with the immediately previous
3895 // sleep/wake.
3896 //
3897 // @param obj has a retain on it. We're responsible for releasing that retain.
3898 //******************************************************************************
3899
3900 void
handleQueueSleepWakeUUID(OSObject * obj)3901 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
3902 {
3903 OSSharedPtr<OSString> str;
3904
3905 if (kOSBooleanFalse == obj) {
3906 handlePublishSleepWakeUUID(false);
3907 } else {
3908 str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
3909 if (str) {
3910 // This branch caches the UUID for an upcoming sleep/wake
3911 queuedSleepWakeUUIDString = str;
3912 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
3913 }
3914 }
3915 }
3916 //******************************************************************************
3917 // handlePublishSleepWakeUUID
3918 //
3919 // Called from IOPMrootDomain when we're initiating a sleep,
3920 // or indirectly from PM configd when PM decides to clear the UUID.
3921 // PM clears the UUID several minutes after successful wake from sleep,
3922 // so that we might associate App spindumps with the immediately previous
3923 // sleep/wake.
3924 //******************************************************************************
3925
3926 void
handlePublishSleepWakeUUID(bool shouldPublish)3927 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
3928 {
3929 ASSERT_GATED();
3930
3931 /*
3932 * Clear the current UUID
3933 */
3934 if (gSleepWakeUUIDIsSet) {
3935 DLOG("SleepWake UUID cleared\n");
3936
3937 gSleepWakeUUIDIsSet = false;
3938
3939 removeProperty(kIOPMSleepWakeUUIDKey);
3940 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
3941 }
3942
3943 /*
3944 * Optionally, publish a new UUID
3945 */
3946 if (queuedSleepWakeUUIDString && shouldPublish) {
3947 OSSharedPtr<OSString> publishThisUUID;
3948
3949 publishThisUUID = queuedSleepWakeUUIDString;
3950
3951 if (publishThisUUID) {
3952 setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
3953 }
3954
3955 gSleepWakeUUIDIsSet = true;
3956 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
3957
3958 queuedSleepWakeUUIDString.reset();
3959 }
3960 }
3961
3962 //******************************************************************************
3963 // IOPMGetSleepWakeUUIDKey
3964 //
3965 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3966 // To get the full key -- a C string -- the buffer must large enough for
3967 // the end-of-string character.
3968 // The key is expected to be an UUID string
3969 //******************************************************************************
3970
3971 extern "C" bool
IOPMCopySleepWakeUUIDKey(char * buffer,size_t buf_len)3972 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
3973 {
3974 if (!gSleepWakeUUIDIsSet) {
3975 return false;
3976 }
3977
3978 if (buffer != NULL) {
3979 OSSharedPtr<OSString> string =
3980 OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
3981
3982 if (!string) {
3983 *buffer = '\0';
3984 } else {
3985 strlcpy(buffer, string->getCStringNoCopy(), buf_len);
3986 }
3987 }
3988
3989 return true;
3990 }
3991
3992 //******************************************************************************
3993 // lowLatencyAudioNotify
3994 //
3995 // Used to send an update about low latency audio activity to interested
3996 // clients. To keep the overhead minimal the OSDictionary used here
3997 // is initialized at boot.
3998 //******************************************************************************
3999
4000 void
lowLatencyAudioNotify(uint64_t time,boolean_t state)4001 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
4002 {
4003 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
4004 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
4005 lowLatencyAudioNotifyTimestampVal->setValue(time);
4006 lowLatencyAudioNotifyStateVal->setValue(state);
4007 setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
4008 } else {
4009 DLOG("LowLatencyAudioNotify error\n");
4010 }
4011 return;
4012 }
4013
4014 //******************************************************************************
4015 // IOPMrootDomainRTNotifier
4016 //
4017 // Used by performance controller to update the timestamp and state associated
4018 // with low latency audio activity in the system.
4019 //******************************************************************************
4020
4021 extern "C" void
IOPMrootDomainRTNotifier(uint64_t time,boolean_t state)4022 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
4023 {
4024 gRootDomain->lowLatencyAudioNotify(time, state);
4025 return;
4026 }
4027
4028 //******************************************************************************
4029 // initializeBootSessionUUID
4030 //
4031 // Initialize the boot session uuid at boot up and sets it into registry.
4032 //******************************************************************************
4033
4034 void
initializeBootSessionUUID(void)4035 IOPMrootDomain::initializeBootSessionUUID(void)
4036 {
4037 uuid_t new_uuid;
4038 uuid_string_t new_uuid_string;
4039
4040 uuid_generate(new_uuid);
4041 uuid_unparse_upper(new_uuid, new_uuid_string);
4042 memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
4043
4044 setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
4045 }
4046
4047 //******************************************************************************
4048 // Root domain uses the private and tagged changePowerState methods for
4049 // tracking and logging purposes.
4050 //******************************************************************************
4051
4052 #define REQUEST_TAG_TO_REASON(x) ((uint16_t)x)
4053
4054 static uint32_t
nextRequestTag(IOPMRequestTag tag)4055 nextRequestTag( IOPMRequestTag tag )
4056 {
4057 static SInt16 msb16 = 1;
4058 uint16_t id = OSAddAtomic16(1, &msb16);
4059 return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
4060 }
4061
4062 // TODO: remove this shim function and exported symbol
4063 IOReturn
changePowerStateTo(unsigned long ordinal)4064 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
4065 {
4066 return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
4067 }
4068
4069 // TODO: remove this shim function and exported symbol
4070 IOReturn
changePowerStateToPriv(unsigned long ordinal)4071 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
4072 {
4073 return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
4074 }
4075
4076 IOReturn
changePowerStateWithOverrideTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4077 IOPMrootDomain::changePowerStateWithOverrideTo(
4078 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4079 {
4080 uint32_t tag = nextRequestTag(reason);
4081 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4082
4083 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4084 return kIOReturnUnsupported;
4085 }
4086
4087 return super::changePowerStateWithOverrideTo(ordinal, tag);
4088 }
4089
4090 IOReturn
changePowerStateWithTagTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4091 IOPMrootDomain::changePowerStateWithTagTo(
4092 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4093 {
4094 uint32_t tag = nextRequestTag(reason);
4095 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4096
4097 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4098 return kIOReturnUnsupported;
4099 }
4100
4101 return super::changePowerStateWithTagTo(ordinal, tag);
4102 }
4103
4104 IOReturn
changePowerStateWithTagToPriv(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4105 IOPMrootDomain::changePowerStateWithTagToPriv(
4106 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4107 {
4108 uint32_t tag = nextRequestTag(reason);
4109 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4110
4111 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4112 return kIOReturnUnsupported;
4113 }
4114
4115 return super::changePowerStateWithTagToPriv(ordinal, tag);
4116 }
4117
4118 //******************************************************************************
4119 // activity detect
4120 //
4121 //******************************************************************************
4122
4123 bool
activitySinceSleep(void)4124 IOPMrootDomain::activitySinceSleep(void)
4125 {
4126 return userActivityCount != userActivityAtSleep;
4127 }
4128
4129 bool
abortHibernation(void)4130 IOPMrootDomain::abortHibernation(void)
4131 {
4132 #if __arm64__
4133 // don't allow hibernation to be aborted on ARM due to user activity
4134 // since once ApplePMGR decides we're hibernating, we can't turn back
4135 // see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4136 return false;
4137 #else
4138 bool ret = activitySinceSleep();
4139
4140 if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4141 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4142 hibernateAborted = true;
4143 }
4144 return ret;
4145 #endif
4146 }
4147
4148 extern "C" int
hibernate_should_abort(void)4149 hibernate_should_abort(void)
4150 {
4151 if (gRootDomain) {
4152 return gRootDomain->abortHibernation();
4153 } else {
4154 return 0;
4155 }
4156 }
4157
4158 //******************************************************************************
4159 // scheduleImmediateDebugWake
4160 //
4161 // Schedule a wake with RTC to wake us back up immediately after we sleep.
4162 // Useful when a cancel request comes in past the revert point on the sleep path
4163 //******************************************************************************
4164
4165 void
scheduleImmediateDebugWake(void)4166 IOPMrootDomain::scheduleImmediateDebugWake( void )
4167 {
4168 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(1);
4169 OSSharedPtr<OSNumber> secs = OSNumber::withNumber(1, 32);
4170
4171 if (dict && secs) {
4172 dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4173 gRootDomain->setProperties(dict.get());
4174 MSG("Reverting sleep with relative wake\n");
4175 }
4176 }
4177
4178 //******************************************************************************
4179 // willNotifyPowerChildren
4180 //
4181 // Called after all interested drivers have all acknowledged the power change,
4182 // but before any power children is informed. Dispatched though a thread call,
4183 // so it is safe to perform work that might block on a sleeping disk. PM state
4184 // machine (not thread) will block w/o timeout until this function returns.
4185 //******************************************************************************
4186
4187 void
willNotifyPowerChildren(IOPMPowerStateIndex newPowerState)4188 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4189 {
4190 if (SLEEP_STATE == newPowerState) {
4191 notifierThread = current_thread();
4192 if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
4193 AbsoluteTime deadline;
4194
4195 clock_interval_to_deadline(10, kSecondScale, &deadline);
4196 #if defined(XNU_TARGET_OS_OSX)
4197 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
4198 #endif /* defined(XNU_TARGET_OS_OSX) */
4199 }
4200
4201 _aotReadyToFullWake = false;
4202 #if 0
4203 if (_aotLingerTime) {
4204 uint64_t deadline;
4205 IOLog("aot linger no return\n");
4206 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
4207 clock_delay_until(deadline);
4208 }
4209 #endif
4210 if (!_aotMode) {
4211 _aotTestTime = 0;
4212 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4213 _aotLastWakeTime = 0;
4214 if (_aotMetrics) {
4215 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4216 }
4217 } else if (!_aotNow && !_debugWakeSeconds) {
4218 _aotNow = true;
4219 _aotPendingFlags = 0;
4220 _aotTasksSuspended = true;
4221 _aotLastWakeTime = 0;
4222 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4223 if (kIOPMAOTModeCycle & _aotMode) {
4224 clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
4225 _aotTestTime = mach_continuous_time() + _aotTestInterval;
4226 setWakeTime(_aotTestTime);
4227 }
4228 uint32_t lingerSecs;
4229 if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
4230 lingerSecs = 0;
4231 }
4232 clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
4233 clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
4234 clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
4235 }
4236
4237 #if HIBERNATION
4238 // Adjust watchdog for IOHibernateSystemSleep
4239 int defaultTimeout = getWatchdogTimeout();
4240 int timeout = defaultTimeout > WATCHDOG_HIBERNATION_TIMEOUT ?
4241 defaultTimeout : WATCHDOG_HIBERNATION_TIMEOUT;
4242 reset_watchdog_timer(timeout);
4243
4244 IOHibernateSystemSleep();
4245 IOHibernateIOKitSleep();
4246 #endif
4247 #if defined(__arm64__) && HIBERNATION
4248 if (gIOHibernateState == kIOHibernateStateInactive) {
4249 setProperty(kIOPMSystemSleepTypeKey, kIOPMSleepTypeDeepIdle, 32);
4250 }
4251 // On AS, hibernation cannot be aborted. Resetting RTC to 1s during hibernation upon detecting
4252 // user activity is pointless (we are likely to spend >1s hibernating). It also clears existing
4253 // alarms, which can mess with cycler tools.
4254 if (gRootDomain->activitySinceSleep() && gIOHibernateState == kIOHibernateStateInactive) {
4255 #else /* defined(__arm64__) && HIBERNATION */
4256 // On non-AS, hibernation can be aborted if user activity is detected. So continue to reset the
4257 // RTC alarm (even during hibernation) so we can immediately wake from regular S2R if needed.
4258 if (gRootDomain->activitySinceSleep()) {
4259 #endif /* defined(__arm64__) && HIBERNATION */
4260 scheduleImmediateDebugWake();
4261 }
4262
4263 notifierThread = NULL;
4264 }
4265 }
4266
4267 //******************************************************************************
4268 // willTellSystemCapabilityDidChange
4269 //
4270 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4271 // domain is raising its power state, immediately after notifying interested
4272 // drivers and power children.
4273 //******************************************************************************
4274
4275 void
4276 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4277 {
4278 if ((_systemTransitionType == kSystemTransitionWake) &&
4279 !CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
4280 // After powering up drivers, dark->full promotion on the current wake
4281 // transition is no longer possible. That is because the next machine
4282 // state will issue the system capability change messages.
4283 // The darkWakePowerClamped flag may already be set if the system has
4284 // at least one driver that was power clamped due to dark wake.
4285 // This function sets the darkWakePowerClamped flag in case there
4286 // is no power-clamped driver in the system.
4287 //
4288 // Last opportunity to exit dark wake using:
4289 // requestFullWake( kFullWakeReasonLocalUser );
4290
4291 if (!darkWakePowerClamped) {
4292 if (darkWakeLogClamp) {
4293 AbsoluteTime now;
4294 uint64_t nsec;
4295
4296 clock_get_uptime(&now);
4297 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
4298 absolutetime_to_nanoseconds(now, &nsec);
4299 DLOG("dark wake promotion disabled at %u ms\n",
4300 ((int)((nsec) / NSEC_PER_MSEC)));
4301 }
4302 darkWakePowerClamped = true;
4303 }
4304 }
4305 }
4306
4307 //******************************************************************************
4308 // sleepOnClamshellClosed
4309 //
4310 // contains the logic to determine if the system should sleep when the clamshell
4311 // is closed.
4312 //******************************************************************************
4313
4314 bool
4315 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4316 {
4317 if (!clamshellExists) {
4318 return false;
4319 }
4320
4321 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4322 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4323
4324 return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4325 }
4326
4327 bool
4328 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4329 {
4330 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4331 // closed && battery
4332 if (!clamshellExists) {
4333 return false;
4334 }
4335
4336 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4337 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4338
4339 return !acAdaptorConnected && !clamshellSleepDisableMask;
4340 }
4341
4342 void
4343 IOPMrootDomain::sendClientClamshellNotification( void )
4344 {
4345 /* Only broadcast clamshell alert if clamshell exists. */
4346 if (!clamshellExists) {
4347 return;
4348 }
4349
4350 setProperty(kAppleClamshellStateKey,
4351 clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4352
4353 setProperty(kAppleClamshellCausesSleepKey,
4354 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4355
4356 /* Argument to message is a bitfiel of
4357 * ( kClamshellStateBit | kClamshellSleepBit )
4358 */
4359 messageClients(kIOPMMessageClamshellStateChange,
4360 (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4361 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4362 }
4363
4364 //******************************************************************************
4365 // getSleepSupported
4366 //
4367 // Deprecated
4368 //******************************************************************************
4369
4370 IOOptionBits
4371 IOPMrootDomain::getSleepSupported( void )
4372 {
4373 return platformSleepSupport;
4374 }
4375
4376 //******************************************************************************
4377 // setSleepSupported
4378 //
4379 // Deprecated
4380 //******************************************************************************
4381
4382 void
4383 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4384 {
4385 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4386 OSBitOrAtomic(flags, &platformSleepSupport);
4387 }
4388
4389 //******************************************************************************
4390 // setClamShellSleepDisable
4391 //
4392 //******************************************************************************
4393
4394 void
4395 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4396 {
4397 uint32_t oldMask;
4398
4399 // User client calls this in non-gated context
4400 if (gIOPMWorkLoop->inGate() == false) {
4401 gIOPMWorkLoop->runAction(
4402 OSMemberFunctionCast(IOWorkLoop::Action, this,
4403 &IOPMrootDomain::setClamShellSleepDisable),
4404 (OSObject *) this,
4405 (void *) disable, (void *)(uintptr_t) bitmask);
4406 return;
4407 }
4408
4409 oldMask = clamshellSleepDisableMask;
4410 if (disable) {
4411 clamshellSleepDisableMask |= bitmask;
4412 } else {
4413 clamshellSleepDisableMask &= ~bitmask;
4414 }
4415 DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4416
4417 if (clamshellExists && clamshellClosed &&
4418 (clamshellSleepDisableMask != oldMask) &&
4419 (clamshellSleepDisableMask == 0)) {
4420 handlePowerNotification(kLocalEvalClamshellCommand);
4421 }
4422 }
4423
4424 //******************************************************************************
4425 // wakeFromDoze
4426 //
4427 // Deprecated.
4428 //******************************************************************************
4429
4430 void
4431 IOPMrootDomain::wakeFromDoze( void )
4432 {
4433 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4434 }
4435
4436 //******************************************************************************
4437 // recordRTCAlarm
4438 //
4439 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4440 // should be a dark wake or a full wake. Both Maintenance and SleepService
4441 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4442 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4443 // PMSettings are ignored.
4444 //
4445 // Caller serialized using settingsCtrlLock.
4446 //******************************************************************************
4447
4448 void
4449 IOPMrootDomain::recordRTCAlarm(
4450 const OSSymbol *type,
4451 OSObject *object )
4452 {
4453 uint32_t previousAlarmMask = _scheduledAlarmMask;
4454
4455 if (type == gIOPMSettingDebugWakeRelativeKey) {
4456 OSNumber * n = OSDynamicCast(OSNumber, object);
4457 if (n) {
4458 // Debug wake has highest scheduling priority so it overrides any
4459 // pre-existing alarm.
4460 uint32_t debugSecs = n->unsigned32BitValue();
4461 _nextScheduledAlarmType.reset(type, OSRetain);
4462 _nextScheduledAlarmUTC = debugSecs;
4463
4464 _debugWakeSeconds = debugSecs;
4465 OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4466 DLOG("next alarm (%s) in %u secs\n",
4467 type->getCStringNoCopy(), debugSecs);
4468 }
4469 } else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) ||
4470 (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) ||
4471 (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) {
4472 OSData * data = OSDynamicCast(OSData, object);
4473 if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) {
4474 const IOPMCalendarStruct * cs;
4475 bool replaceNextAlarm = false;
4476 clock_sec_t secs;
4477
4478 cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4479 secs = IOPMConvertCalendarToSeconds(cs);
4480 DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4481
4482 // Update the next scheduled alarm type
4483 if ((_nextScheduledAlarmType == NULL) ||
4484 ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4485 (secs < _nextScheduledAlarmUTC))) {
4486 replaceNextAlarm = true;
4487 }
4488
4489 if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4490 if (cs->year) {
4491 _calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4492 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4493 } else {
4494 // TODO: can this else-block be removed?
4495 _calendarWakeAlarmUTC = 0;
4496 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4497 }
4498 }
4499 if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4500 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4501 }
4502 if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4503 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4504 }
4505
4506 if (replaceNextAlarm) {
4507 _nextScheduledAlarmType.reset(type, OSRetain);
4508 _nextScheduledAlarmUTC = secs;
4509 DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4510 }
4511 }
4512 }
4513
4514 if (_scheduledAlarmMask != previousAlarmMask) {
4515 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4516 }
4517 }
4518
4519 // MARK: -
4520 // MARK: Features
4521
4522 //******************************************************************************
4523 // publishFeature
4524 //
4525 // Adds a new feature to the supported features dictionary
4526 //******************************************************************************
4527
4528 void
4529 IOPMrootDomain::publishFeature( const char * feature )
4530 {
4531 publishFeature(feature, kRD_AllPowerSources, NULL);
4532 }
4533
4534 //******************************************************************************
4535 // publishFeature (with supported power source specified)
4536 //
4537 // Adds a new feature to the supported features dictionary
4538 //******************************************************************************
4539
4540 void
4541 IOPMrootDomain::publishFeature(
4542 const char *feature,
4543 uint32_t supportedWhere,
4544 uint32_t *uniqueFeatureID)
4545 {
4546 static uint16_t next_feature_id = 500;
4547
4548 OSSharedPtr<OSNumber> new_feature_data;
4549 OSNumber *existing_feature = NULL;
4550 OSArray *existing_feature_arr_raw = NULL;
4551 OSSharedPtr<OSArray> existing_feature_arr;
4552 OSObject *osObj = NULL;
4553 uint32_t feature_value = 0;
4554
4555 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4556
4557 if (!supportedWhere) {
4558 // Feature isn't supported anywhere!
4559 return;
4560 }
4561
4562 if (next_feature_id > 5000) {
4563 // Far, far too many features!
4564 return;
4565 }
4566
4567 if (featuresDictLock) {
4568 IOLockLock(featuresDictLock);
4569 }
4570
4571 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4572 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4573 OSSharedPtr<OSDictionary> features;
4574
4575 // Create new features dict if necessary
4576 if (origFeatures) {
4577 features = OSDictionary::withDictionary(origFeatures);
4578 } else {
4579 features = OSDictionary::withCapacity(1);
4580 }
4581
4582 // Create OSNumber to track new feature
4583
4584 next_feature_id += 1;
4585 if (uniqueFeatureID) {
4586 // We don't really mind if the calling kext didn't give us a place
4587 // to stash their unique id. Many kexts don't plan to unload, and thus
4588 // have no need to remove themselves later.
4589 *uniqueFeatureID = next_feature_id;
4590 }
4591
4592 feature_value = (uint32_t)next_feature_id;
4593 feature_value <<= 16;
4594 feature_value += supportedWhere;
4595
4596 new_feature_data = OSNumber::withNumber(
4597 (unsigned long long)feature_value, 32);
4598
4599 // Does features object already exist?
4600 if ((osObj = features->getObject(feature))) {
4601 if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
4602 // We need to create an OSArray to hold the now 2 elements.
4603 existing_feature_arr = OSArray::withObjects(
4604 (const OSObject **)&existing_feature, 1, 2);
4605 } else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) {
4606 // Add object to existing array
4607 existing_feature_arr = OSArray::withArray(
4608 existing_feature_arr_raw,
4609 existing_feature_arr_raw->getCount() + 1);
4610 }
4611
4612 if (existing_feature_arr) {
4613 existing_feature_arr->setObject(new_feature_data.get());
4614 features->setObject(feature, existing_feature_arr.get());
4615 }
4616 } else {
4617 // The easy case: no previously existing features listed. We simply
4618 // set the OSNumber at key 'feature' and we're on our way.
4619 features->setObject(feature, new_feature_data.get());
4620 }
4621
4622 setProperty(kRootDomainSupportedFeatures, features.get());
4623
4624 if (featuresDictLock) {
4625 IOLockUnlock(featuresDictLock);
4626 }
4627
4628 // Notify EnergySaver and all those in user space so they might
4629 // re-populate their feature specific UI
4630 if (pmPowerStateQueue) {
4631 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4632 }
4633 }
4634
4635 //******************************************************************************
4636 // removePublishedFeature
4637 //
4638 // Removes previously published feature
4639 //******************************************************************************
4640
4641 IOReturn
4642 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4643 {
4644 IOReturn ret = kIOReturnError;
4645 uint32_t feature_value = 0;
4646 uint16_t feature_id = 0;
4647 bool madeAChange = false;
4648
4649 OSSymbol *dictKey = NULL;
4650 OSSharedPtr<OSCollectionIterator> dictIterator;
4651 OSArray *arrayMember = NULL;
4652 OSNumber *numberMember = NULL;
4653 OSObject *osObj = NULL;
4654 OSNumber *osNum = NULL;
4655 OSSharedPtr<OSArray> arrayMemberCopy;
4656
4657 if (kBadPMFeatureID == removeFeatureID) {
4658 return kIOReturnNotFound;
4659 }
4660
4661 if (featuresDictLock) {
4662 IOLockLock(featuresDictLock);
4663 }
4664
4665 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4666 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4667 OSSharedPtr<OSDictionary> features;
4668
4669 if (origFeatures) {
4670 // Any modifications to the dictionary are made to the copy to prevent
4671 // races & crashes with userland clients. Dictionary updated
4672 // automically later.
4673 features = OSDictionary::withDictionary(origFeatures);
4674 } else {
4675 features = NULL;
4676 ret = kIOReturnNotFound;
4677 goto exit;
4678 }
4679
4680 // We iterate 'features' dictionary looking for an entry tagged
4681 // with 'removeFeatureID'. If found, we remove it from our tracking
4682 // structures and notify the OS via a general interest message.
4683
4684 dictIterator = OSCollectionIterator::withCollection(features.get());
4685 if (!dictIterator) {
4686 goto exit;
4687 }
4688
4689 while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4690 osObj = features->getObject(dictKey);
4691
4692 // Each Feature is either tracked by an OSNumber
4693 if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
4694 feature_value = numberMember->unsigned32BitValue();
4695 feature_id = (uint16_t)(feature_value >> 16);
4696
4697 if (feature_id == (uint16_t)removeFeatureID) {
4698 // Remove this node
4699 features->removeObject(dictKey);
4700 madeAChange = true;
4701 break;
4702 }
4703
4704 // Or tracked by an OSArray of OSNumbers
4705 } else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4706 unsigned int arrayCount = arrayMember->getCount();
4707
4708 for (unsigned int i = 0; i < arrayCount; i++) {
4709 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4710 if (!osNum) {
4711 continue;
4712 }
4713
4714 feature_value = osNum->unsigned32BitValue();
4715 feature_id = (uint16_t)(feature_value >> 16);
4716
4717 if (feature_id == (uint16_t)removeFeatureID) {
4718 // Remove this node
4719 if (1 == arrayCount) {
4720 // If the array only contains one element, remove
4721 // the whole thing.
4722 features->removeObject(dictKey);
4723 } else {
4724 // Otherwise remove the element from a copy of the array.
4725 arrayMemberCopy = OSArray::withArray(arrayMember);
4726 if (arrayMemberCopy) {
4727 arrayMemberCopy->removeObject(i);
4728 features->setObject(dictKey, arrayMemberCopy.get());
4729 }
4730 }
4731
4732 madeAChange = true;
4733 break;
4734 }
4735 }
4736 }
4737 }
4738
4739 if (madeAChange) {
4740 ret = kIOReturnSuccess;
4741
4742 setProperty(kRootDomainSupportedFeatures, features.get());
4743
4744 // Notify EnergySaver and all those in user space so they might
4745 // re-populate their feature specific UI
4746 if (pmPowerStateQueue) {
4747 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4748 }
4749 } else {
4750 ret = kIOReturnNotFound;
4751 }
4752
4753 exit:
4754 if (featuresDictLock) {
4755 IOLockUnlock(featuresDictLock);
4756 }
4757 return ret;
4758 }
4759
4760 //******************************************************************************
4761 // publishPMSetting (private)
4762 //
4763 // Should only be called by PMSettingObject to publish a PM Setting as a
4764 // supported feature.
4765 //******************************************************************************
4766
4767 void
4768 IOPMrootDomain::publishPMSetting(
4769 const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4770 {
4771 if (noPublishPMSettings &&
4772 (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4773 // Setting found in noPublishPMSettings array
4774 *featureID = kBadPMFeatureID;
4775 return;
4776 }
4777
4778 publishFeature(
4779 feature->getCStringNoCopy(), where, featureID);
4780 }
4781
4782 //******************************************************************************
4783 // setPMSetting (private)
4784 //
4785 // Internal helper to relay PM settings changes from user space to individual
4786 // drivers. Should be called only by IOPMrootDomain::setProperties.
4787 //******************************************************************************
4788
4789 IOReturn
4790 IOPMrootDomain::setPMSetting(
4791 const OSSymbol *type,
4792 OSObject *object )
4793 {
4794 PMSettingCallEntry *entries = NULL;
4795 OSSharedPtr<OSArray> chosen;
4796 const OSArray *array;
4797 PMSettingObject *pmso;
4798 thread_t thisThread;
4799 int i, j, count, capacity;
4800 bool ok = false;
4801 IOReturn ret;
4802
4803 if (NULL == type) {
4804 return kIOReturnBadArgument;
4805 }
4806
4807 PMSETTING_LOCK();
4808
4809 // Update settings dict so changes are visible from copyPMSetting().
4810 fPMSettingsDict->setObject(type, object);
4811
4812 // Prep all PMSetting objects with the given 'type' for callout.
4813 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
4814 if (!array || ((capacity = array->getCount()) == 0)) {
4815 goto unlock_exit;
4816 }
4817
4818 // Array to retain PMSetting objects targeted for callout.
4819 chosen = OSArray::withCapacity(capacity);
4820 if (!chosen) {
4821 goto unlock_exit; // error
4822 }
4823 entries = IONew(PMSettingCallEntry, capacity);
4824 if (!entries) {
4825 goto unlock_exit; // error
4826 }
4827 memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4828
4829 thisThread = current_thread();
4830
4831 for (i = 0, j = 0; i < capacity; i++) {
4832 pmso = (PMSettingObject *) array->getObject(i);
4833 if (pmso->disabled) {
4834 continue;
4835 }
4836 entries[j].thread = thisThread;
4837 queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4838 chosen->setObject(pmso);
4839 j++;
4840 }
4841 count = j;
4842 if (!count) {
4843 goto unlock_exit;
4844 }
4845
4846 PMSETTING_UNLOCK();
4847
4848 // Call each pmso in the chosen array.
4849 for (i = 0; i < count; i++) {
4850 pmso = (PMSettingObject *) chosen->getObject(i);
4851 ret = pmso->dispatchPMSetting(type, object);
4852 if (ret == kIOReturnSuccess) {
4853 // At least one setting handler was successful
4854 ok = true;
4855 #if DEVELOPMENT || DEBUG
4856 } else {
4857 // Log the handler and kext that failed
4858 OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
4859 if (kextName) {
4860 DLOG("PMSetting(%s) error 0x%x from %s\n",
4861 type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
4862 }
4863 #endif
4864 }
4865 }
4866
4867 PMSETTING_LOCK();
4868 for (i = 0; i < count; i++) {
4869 pmso = (PMSettingObject *) chosen->getObject(i);
4870 queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
4871 if (pmso->waitThread) {
4872 PMSETTING_WAKEUP(pmso);
4873 }
4874 }
4875
4876 if (ok) {
4877 recordRTCAlarm(type, object);
4878 }
4879 unlock_exit:
4880 PMSETTING_UNLOCK();
4881
4882 if (entries) {
4883 IODelete(entries, PMSettingCallEntry, capacity);
4884 }
4885
4886 return kIOReturnSuccess;
4887 }
4888
4889 //******************************************************************************
4890 // copyPMSetting (public)
4891 //
4892 // Allows kexts to safely read setting values, without being subscribed to
4893 // notifications.
4894 //******************************************************************************
4895
4896 OSSharedPtr<OSObject>
4897 IOPMrootDomain::copyPMSetting(
4898 OSSymbol *whichSetting)
4899 {
4900 OSSharedPtr<OSObject> obj;
4901
4902 if (!whichSetting) {
4903 return NULL;
4904 }
4905
4906 PMSETTING_LOCK();
4907 obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
4908 PMSETTING_UNLOCK();
4909
4910 return obj;
4911 }
4912
4913 //******************************************************************************
4914 // registerPMSettingController (public)
4915 //
4916 // direct wrapper to registerPMSettingController with uint32_t power source arg
4917 //******************************************************************************
4918
4919 IOReturn
4920 IOPMrootDomain::registerPMSettingController(
4921 const OSSymbol * settings[],
4922 IOPMSettingControllerCallback func,
4923 OSObject *target,
4924 uintptr_t refcon,
4925 OSObject **handle)
4926 {
4927 return registerPMSettingController(
4928 settings,
4929 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
4930 func, target, refcon, handle);
4931 }
4932
4933 //******************************************************************************
4934 // registerPMSettingController (public)
4935 //
4936 // Kexts may register for notifications when a particular setting is changed.
4937 // A list of settings is available in IOPM.h.
4938 // Arguments:
4939 // * settings - An OSArray containing OSSymbols. Caller should populate this
4940 // array with a list of settings caller wants notifications from.
4941 // * func - A C function callback of the type IOPMSettingControllerCallback
4942 // * target - caller may provide an OSObject *, which PM will pass as an
4943 // target to calls to "func"
4944 // * refcon - caller may provide an void *, which PM will pass as an
4945 // argument to calls to "func"
4946 // * handle - This is a return argument. We will populate this pointer upon
4947 // call success. Hold onto this and pass this argument to
4948 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4949 // Returns:
4950 // kIOReturnSuccess on success
4951 //******************************************************************************
4952
4953 IOReturn
4954 IOPMrootDomain::registerPMSettingController(
4955 const OSSymbol * settings[],
4956 uint32_t supportedPowerSources,
4957 IOPMSettingControllerCallback func,
4958 OSObject *target,
4959 uintptr_t refcon,
4960 OSObject **handle)
4961 {
4962 PMSettingObject *pmso = NULL;
4963 OSObject *pmsh = NULL;
4964 int i;
4965
4966 if (NULL == settings ||
4967 NULL == func ||
4968 NULL == handle) {
4969 return kIOReturnBadArgument;
4970 }
4971
4972 pmso = PMSettingObject::pmSettingObject(
4973 (IOPMrootDomain *) this, func, target,
4974 refcon, supportedPowerSources, settings, &pmsh);
4975
4976 if (!pmso) {
4977 *handle = NULL;
4978 return kIOReturnInternalError;
4979 }
4980
4981 PMSETTING_LOCK();
4982 for (i = 0; settings[i]; i++) {
4983 OSSharedPtr<OSArray> newList;
4984 OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
4985 if (!list) {
4986 // New array of callbacks for this setting
4987 newList = OSArray::withCapacity(1);
4988 settingsCallbacks->setObject(settings[i], newList.get());
4989 list = newList.get();
4990 }
4991
4992 // Add caller to the callback list
4993 list->setObject(pmso);
4994 }
4995 PMSETTING_UNLOCK();
4996
4997 // Return handle to the caller, the setting object is private.
4998 *handle = pmsh;
4999
5000 return kIOReturnSuccess;
5001 }
5002
5003 //******************************************************************************
5004 // deregisterPMSettingObject (private)
5005 //
5006 // Only called from PMSettingObject.
5007 //******************************************************************************
5008
5009 void
5010 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
5011 {
5012 thread_t thisThread = current_thread();
5013 PMSettingCallEntry *callEntry;
5014 OSSharedPtr<OSCollectionIterator> iter;
5015 OSSymbol *sym;
5016 OSArray *array;
5017 int index;
5018 bool wait;
5019
5020 PMSETTING_LOCK();
5021
5022 pmso->disabled = true;
5023
5024 // Wait for all callout threads to finish.
5025 do {
5026 wait = false;
5027 queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
5028 {
5029 if (callEntry->thread != thisThread) {
5030 wait = true;
5031 break;
5032 }
5033 }
5034 if (wait) {
5035 assert(NULL == pmso->waitThread);
5036 pmso->waitThread = thisThread;
5037 PMSETTING_WAIT(pmso);
5038 pmso->waitThread = NULL;
5039 }
5040 } while (wait);
5041
5042 // Search each PM settings array in the kernel.
5043 iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
5044 if (iter) {
5045 while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
5046 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
5047 index = array->getNextIndexOfObject(pmso, 0);
5048 if (-1 != index) {
5049 array->removeObject(index);
5050 }
5051 }
5052 }
5053
5054 PMSETTING_UNLOCK();
5055
5056 pmso->release();
5057 }
5058
5059 //******************************************************************************
5060 // informCPUStateChange
5061 //
5062 // Call into PM CPU code so that CPU power savings may dynamically adjust for
5063 // running on battery, with the lid closed, etc.
5064 //
5065 // informCPUStateChange is a no-op on non x86 systems
5066 // only x86 has explicit support in the IntelCPUPowerManagement kext
5067 //******************************************************************************
5068
5069 void
5070 IOPMrootDomain::informCPUStateChange(
5071 uint32_t type,
5072 uint32_t value )
5073 {
5074 #if defined(__i386__) || defined(__x86_64__)
5075
5076 pmioctlVariableInfo_t varInfoStruct;
5077 int pmCPUret = 0;
5078 const char *varNameStr = NULL;
5079 int32_t *varIndex = NULL;
5080
5081 if (kInformAC == type) {
5082 varNameStr = kIOPMRootDomainBatPowerCString;
5083 varIndex = &idxPMCPULimitedPower;
5084 } else if (kInformLid == type) {
5085 varNameStr = kIOPMRootDomainLidCloseCString;
5086 varIndex = &idxPMCPUClamshell;
5087 } else {
5088 return;
5089 }
5090
5091 // Set the new value!
5092 // pmCPUControl will assign us a new ID if one doesn't exist yet
5093 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
5094 varInfoStruct.varID = *varIndex;
5095 varInfoStruct.varType = vBool;
5096 varInfoStruct.varInitValue = value;
5097 varInfoStruct.varCurValue = value;
5098 strlcpy((char *)varInfoStruct.varName,
5099 (const char *)varNameStr,
5100 sizeof(varInfoStruct.varName));
5101
5102 // Set!
5103 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
5104
5105 // pmCPU only assigns numerical id's when a new varName is specified
5106 if ((0 == pmCPUret)
5107 && (*varIndex == kCPUUnknownIndex)) {
5108 // pmCPUControl has assigned us a new variable ID.
5109 // Let's re-read the structure we just SET to learn that ID.
5110 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
5111
5112 if (0 == pmCPUret) {
5113 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5114 *varIndex = varInfoStruct.varID;
5115 }
5116 }
5117
5118 return;
5119
5120 #endif /* __i386__ || __x86_64__ */
5121 }
5122
5123 // MARK: -
5124 // MARK: Deep Sleep Policy
5125
5126 #if HIBERNATION
5127
5128 //******************************************************************************
5129 // evaluateSystemSleepPolicy
5130 //******************************************************************************
5131
5132 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
5133
5134 // Sleep flags
5135 enum {
5136 kIOPMSleepFlagHibernate = 0x00000001,
5137 kIOPMSleepFlagSleepTimerEnable = 0x00000002
5138 };
5139
5140 struct IOPMSystemSleepPolicyEntry {
5141 uint32_t factorMask;
5142 uint32_t factorBits;
5143 uint32_t sleepFlags;
5144 uint32_t wakeEvents;
5145 } __attribute__((packed));
5146
5147 struct IOPMSystemSleepPolicyTable {
5148 uint32_t signature;
5149 uint16_t version;
5150 uint16_t entryCount;
5151 IOPMSystemSleepPolicyEntry entries[];
5152 } __attribute__((packed));
5153
5154 enum {
5155 kIOPMSleepAttributeHibernateSetup = 0x00000001,
5156 kIOPMSleepAttributeHibernateSleep = 0x00000002
5157 };
5158
5159 static uint32_t
5160 getSleepTypeAttributes( uint32_t sleepType )
5161 {
5162 static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5163 {
5164 /* invalid */ 0,
5165 /* abort */ 0,
5166 /* normal */ 0,
5167 /* safesleep */ kIOPMSleepAttributeHibernateSetup,
5168 /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5169 /* standby */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5170 /* poweroff */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5171 /* deepidle */ 0
5172 };
5173
5174 if (sleepType >= kIOPMSleepTypeLast) {
5175 return 0;
5176 }
5177
5178 return sleepTypeAttributes[sleepType];
5179 }
5180
5181 bool
5182 IOPMrootDomain::evaluateSystemSleepPolicy(
5183 IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5184 {
5185 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5186
5187 static const IONamedValue factorValues[] = {
5188 SLEEP_FACTOR( SleepTimerWake ),
5189 SLEEP_FACTOR( LidOpen ),
5190 SLEEP_FACTOR( ACPower ),
5191 SLEEP_FACTOR( BatteryLow ),
5192 SLEEP_FACTOR( StandbyNoDelay ),
5193 SLEEP_FACTOR( StandbyForced ),
5194 SLEEP_FACTOR( StandbyDisabled ),
5195 SLEEP_FACTOR( USBExternalDevice ),
5196 SLEEP_FACTOR( BluetoothHIDDevice ),
5197 SLEEP_FACTOR( ExternalMediaMounted ),
5198 SLEEP_FACTOR( ThunderboltDevice ),
5199 SLEEP_FACTOR( RTCAlarmScheduled ),
5200 SLEEP_FACTOR( MagicPacketWakeEnabled ),
5201 SLEEP_FACTOR( HibernateForced ),
5202 SLEEP_FACTOR( AutoPowerOffDisabled ),
5203 SLEEP_FACTOR( AutoPowerOffForced ),
5204 SLEEP_FACTOR( ExternalDisplay ),
5205 SLEEP_FACTOR( NetworkKeepAliveActive ),
5206 SLEEP_FACTOR( LocalUserActivity ),
5207 SLEEP_FACTOR( HibernateFailed ),
5208 SLEEP_FACTOR( ThermalWarning ),
5209 SLEEP_FACTOR( DisplayCaptured ),
5210 { 0, NULL }
5211 };
5212
5213 const IOPMSystemSleepPolicyTable * pt;
5214 OSSharedPtr<OSObject> prop;
5215 OSData * policyData;
5216 uint64_t currentFactors = 0;
5217 char currentFactorsBuf[512];
5218 uint32_t standbyDelay = 0;
5219 uint32_t powerOffDelay = 0;
5220 uint32_t powerOffTimer = 0;
5221 uint32_t standbyTimer = 0;
5222 uint32_t mismatch;
5223 bool standbyEnabled;
5224 bool powerOffEnabled;
5225 bool found = false;
5226
5227 // Get platform's sleep policy table
5228 if (!gSleepPolicyHandler) {
5229 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5230 if (!prop) {
5231 goto done;
5232 }
5233 }
5234
5235 // Fetch additional settings
5236 standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
5237 && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue));
5238 powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
5239 && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue));
5240 if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
5241 powerOffTimer = powerOffDelay;
5242 }
5243 if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5244 standbyTimer = standbyDelay;
5245 }
5246
5247 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5248 sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
5249 powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
5250
5251 currentFactorsBuf[0] = 0;
5252 // pmset level overrides
5253 if ((*hibMode & kIOHibernateModeOn) == 0) {
5254 if (!gSleepPolicyHandler) {
5255 standbyEnabled = false;
5256 powerOffEnabled = false;
5257 }
5258 } else if (!(*hibMode & kIOHibernateModeSleep)) {
5259 // Force hibernate (i.e. mode 25)
5260 // If standby is enabled, force standy.
5261 // If poweroff is enabled, force poweroff.
5262 if (standbyEnabled) {
5263 currentFactors |= kIOPMSleepFactorStandbyForced;
5264 } else if (powerOffEnabled) {
5265 currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
5266 } else {
5267 currentFactors |= kIOPMSleepFactorHibernateForced;
5268 }
5269 }
5270
5271 // Current factors based on environment and assertions
5272 if (sleepTimerMaintenance) {
5273 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5274 }
5275 if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5276 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5277 }
5278 if (!clamshellClosed) {
5279 currentFactors |= kIOPMSleepFactorLidOpen;
5280 }
5281 if (acAdaptorConnected) {
5282 currentFactors |= kIOPMSleepFactorACPower;
5283 }
5284 if (lowBatteryCondition) {
5285 hibernateMode = 0;
5286 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5287 if ((hibernateMode & kIOHibernateModeOn) == 0) {
5288 DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5289 } else {
5290 currentFactors |= kIOPMSleepFactorBatteryLow;
5291 }
5292 }
5293 if (!standbyDelay || !standbyTimer) {
5294 currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5295 }
5296 if (standbyNixed || !standbyEnabled) {
5297 currentFactors |= kIOPMSleepFactorStandbyDisabled;
5298 }
5299 if (resetTimers) {
5300 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5301 currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5302 }
5303 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5304 kIOPMDriverAssertionLevelOff) {
5305 currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5306 }
5307 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5308 kIOPMDriverAssertionLevelOff) {
5309 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5310 }
5311 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5312 kIOPMDriverAssertionLevelOff) {
5313 currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5314 }
5315 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5316 kIOPMDriverAssertionLevelOff) {
5317 currentFactors |= kIOPMSleepFactorThunderboltDevice;
5318 }
5319 if (_scheduledAlarmMask != 0) {
5320 currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5321 }
5322 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5323 kIOPMDriverAssertionLevelOff) {
5324 currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5325 }
5326 #define TCPKEEPALIVE 1
5327 #if TCPKEEPALIVE
5328 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5329 kIOPMDriverAssertionLevelOff) {
5330 currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5331 }
5332 #endif
5333 if (!powerOffEnabled) {
5334 currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5335 }
5336 if (desktopMode) {
5337 currentFactors |= kIOPMSleepFactorExternalDisplay;
5338 }
5339 if (userWasActive) {
5340 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5341 }
5342 if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5343 currentFactors |= kIOPMSleepFactorHibernateFailed;
5344 }
5345 if (thermalWarningState) {
5346 currentFactors |= kIOPMSleepFactorThermalWarning;
5347 }
5348
5349 for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) {
5350 uint32_t factor = 1 << factorBit;
5351 if (factor & currentFactors) {
5352 strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf));
5353 strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf));
5354 }
5355 }
5356 DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5357
5358 if (gSleepPolicyHandler) {
5359 uint32_t savedHibernateMode;
5360 IOReturn result;
5361
5362 if (!gSleepPolicyVars) {
5363 gSleepPolicyVars = IOMallocType(IOPMSystemSleepPolicyVariables);
5364 }
5365 gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
5366 gSleepPolicyVars->version = kIOPMSystemSleepPolicyVersion;
5367 gSleepPolicyVars->currentCapability = _currentCapability;
5368 gSleepPolicyVars->highestCapability = _highestCapability;
5369 gSleepPolicyVars->sleepFactors = currentFactors;
5370 gSleepPolicyVars->sleepReason = lastSleepReason;
5371 gSleepPolicyVars->sleepPhase = sleepPhase;
5372 gSleepPolicyVars->standbyDelay = standbyDelay;
5373 gSleepPolicyVars->standbyTimer = standbyTimer;
5374 gSleepPolicyVars->poweroffDelay = powerOffDelay;
5375 gSleepPolicyVars->scheduledAlarms = _scheduledAlarmMask | _userScheduledAlarmMask;
5376 gSleepPolicyVars->poweroffTimer = powerOffTimer;
5377
5378 if (kIOPMSleepPhase0 == sleepPhase) {
5379 // preserve hibernateMode
5380 savedHibernateMode = gSleepPolicyVars->hibernateMode;
5381 gSleepPolicyVars->hibernateMode = *hibMode;
5382 } else if (kIOPMSleepPhase1 == sleepPhase) {
5383 // use original hibernateMode for phase2
5384 gSleepPolicyVars->hibernateMode = *hibMode;
5385 }
5386
5387 result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5388
5389 if (kIOPMSleepPhase0 == sleepPhase) {
5390 // restore hibernateMode
5391 gSleepPolicyVars->hibernateMode = savedHibernateMode;
5392 }
5393
5394 if ((result != kIOReturnSuccess) ||
5395 (kIOPMSleepTypeInvalid == params->sleepType) ||
5396 (params->sleepType >= kIOPMSleepTypeLast) ||
5397 (kIOPMSystemSleepParametersVersion != params->version)) {
5398 MSG("sleep policy handler error\n");
5399 goto done;
5400 }
5401
5402 if ((getSleepTypeAttributes(params->sleepType) &
5403 kIOPMSleepAttributeHibernateSetup) &&
5404 ((*hibMode & kIOHibernateModeOn) == 0)) {
5405 *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5406 }
5407
5408 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5409 params->version, params->sleepType, params->sleepFlags,
5410 params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
5411 found = true;
5412 goto done;
5413 }
5414
5415 // Policy table is meaningless without standby enabled
5416 if (!standbyEnabled) {
5417 goto done;
5418 }
5419
5420 // Validate the sleep policy table
5421 policyData = OSDynamicCast(OSData, prop.get());
5422 if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5423 goto done;
5424 }
5425
5426 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5427 if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5428 (pt->version != 1) || (0 == pt->entryCount)) {
5429 goto done;
5430 }
5431
5432 if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5433 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5434 goto done;
5435 }
5436
5437 for (uint32_t i = 0; i < pt->entryCount; i++) {
5438 const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
5439 mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
5440
5441 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5442 entry->factorMask, entry->factorBits,
5443 entry->sleepFlags, entry->wakeEvents, mismatch);
5444 if (mismatch) {
5445 continue;
5446 }
5447
5448 DLOG("^ found match\n");
5449 found = true;
5450
5451 params->version = kIOPMSystemSleepParametersVersion;
5452 params->reserved1 = 1;
5453 if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5454 params->sleepType = kIOPMSleepTypeStandby;
5455 } else {
5456 params->sleepType = kIOPMSleepTypeNormalSleep;
5457 }
5458
5459 params->ecWakeEvents = entry->wakeEvents;
5460 if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5461 if (kIOPMSleepPhase2 == sleepPhase) {
5462 clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5463
5464 if (!_standbyTimerResetSeconds ||
5465 (now_secs <= _standbyTimerResetSeconds)) {
5466 // Reset standby timer adjustment
5467 _standbyTimerResetSeconds = now_secs;
5468 DLOG("standby delay %u, reset %u\n",
5469 standbyDelay, (uint32_t) _standbyTimerResetSeconds);
5470 } else if (standbyDelay) {
5471 // Shorten the standby delay timer
5472 clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
5473 if (standbyDelay > elapsed) {
5474 standbyDelay -= elapsed;
5475 } else {
5476 standbyDelay = 1; // must be > 0
5477 }
5478 DLOG("standby delay %u, elapsed %u\n",
5479 standbyDelay, (uint32_t) elapsed);
5480 }
5481 }
5482 params->ecWakeTimer = standbyDelay;
5483 } else if (kIOPMSleepPhase2 == sleepPhase) {
5484 // A sleep that does not enable the sleep timer will reset
5485 // the standby delay adjustment.
5486 _standbyTimerResetSeconds = 0;
5487 }
5488 break;
5489 }
5490
5491 done:
5492 return found;
5493 }
5494
5495 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5496
5497 void
5498 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5499 {
5500 // Evaluate early (priority interest phase), before drivers sleep.
5501
5502 DLOG("%s\n", __FUNCTION__);
5503 removeProperty(kIOPMSystemSleepParametersKey);
5504
5505 // Full wake resets the standby timer delay adjustment
5506 if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5507 _standbyTimerResetSeconds = 0;
5508 }
5509
5510 hibernateDisabled = false;
5511 hibernateMode = 0;
5512 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5513
5514 // Save for late evaluation if sleep is aborted
5515 bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5516
5517 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5518 &hibernateMode)) {
5519 if (!hibernateRetry &&
5520 ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5521 kIOPMSleepAttributeHibernateSetup) == 0)) {
5522 // skip hibernate setup
5523 hibernateDisabled = true;
5524 }
5525 }
5526
5527 // Publish IOPMSystemSleepType
5528 uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5529 if (sleepType == kIOPMSleepTypeInvalid) {
5530 // no sleep policy
5531 sleepType = kIOPMSleepTypeNormalSleep;
5532 if (hibernateMode & kIOHibernateModeOn) {
5533 sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5534 kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5535 }
5536 } else if ((sleepType == kIOPMSleepTypeStandby) &&
5537 (gEarlySystemSleepParams.ecPoweroffTimer)) {
5538 // report the lowest possible sleep state
5539 sleepType = kIOPMSleepTypePowerOff;
5540 }
5541
5542 setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5543 }
5544
5545 void
5546 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5547 {
5548 IOPMSystemSleepParameters params;
5549 OSSharedPtr<OSData> paramsData;
5550 bool wakeNow;
5551 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5552
5553 DLOG("%s\n", __FUNCTION__);
5554
5555 bzero(¶ms, sizeof(params));
5556 wakeNow = false;
5557 if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2, &hibernateMode)) {
5558 if ((kIOPMSleepTypeStandby == params.sleepType)
5559 && gIOHibernateStandbyDisabled && gSleepPolicyVars
5560 && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5561 & gSleepPolicyVars->sleepFactors))) {
5562 standbyNixed = true;
5563 wakeNow = true;
5564 }
5565 if (wakeNow
5566 || ((hibernateDisabled || hibernateAborted) &&
5567 (getSleepTypeAttributes(params.sleepType) &
5568 kIOPMSleepAttributeHibernateSetup))) {
5569 // Final evaluation picked a state requiring hibernation,
5570 // but hibernate isn't going to proceed. Arm a short sleep using
5571 // the early non-hibernate sleep parameters.
5572 bcopy(&gEarlySystemSleepParams, ¶ms, sizeof(params));
5573 params.sleepType = kIOPMSleepTypeAbortedSleep;
5574 params.ecWakeTimer = 1;
5575 if (standbyNixed) {
5576 resetTimers = true;
5577 } else {
5578 // Set hibernateRetry flag to force hibernate setup on the
5579 // next sleep.
5580 hibernateRetry = true;
5581 }
5582 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5583 params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5584 } else {
5585 hibernateRetry = false;
5586 }
5587
5588 if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5589 resetTimers = false;
5590 }
5591
5592 paramsData = OSData::withValue(params);
5593 if (paramsData) {
5594 setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5595 }
5596
5597 if (getSleepTypeAttributes(params.sleepType) &
5598 kIOPMSleepAttributeHibernateSleep) {
5599 // Disable sleep to force hibernation
5600 gIOHibernateMode &= ~kIOHibernateModeSleep;
5601 }
5602 }
5603 }
5604
5605 bool
5606 IOPMrootDomain::getHibernateSettings(
5607 uint32_t * hibernateModePtr,
5608 uint32_t * hibernateFreeRatio,
5609 uint32_t * hibernateFreeTime )
5610 {
5611 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5612 // has updated the hibernateDisabled flag.
5613
5614 bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
5615 getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
5616 getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
5617 if (hibernateDisabled) {
5618 *hibernateModePtr = 0;
5619 } else if (gSleepPolicyHandler) {
5620 *hibernateModePtr = hibernateMode;
5621 }
5622 DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5623 return ok;
5624 }
5625
5626 bool
5627 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5628 {
5629 OSSharedPtr<OSObject> optionsProp;
5630 OSDictionary * optionsDict;
5631 OSSharedPtr<OSObject> obj;
5632 OSNumber * num;
5633 bool ok = false;
5634
5635 optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5636 optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5637
5638 if (optionsDict) {
5639 obj.reset(optionsDict->getObject(key), OSRetain);
5640 }
5641 if (!obj) {
5642 obj = copyProperty(key);
5643 }
5644 if (obj) {
5645 if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5646 *option = num->unsigned32BitValue();
5647 ok = true;
5648 } else if (OSDynamicCast(OSBoolean, obj.get())) {
5649 *option = (obj == kOSBooleanTrue) ? 1 : 0;
5650 ok = true;
5651 }
5652 }
5653
5654 return ok;
5655 }
5656 #endif /* HIBERNATION */
5657
5658 IOReturn
5659 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5660 {
5661 #if HIBERNATION
5662 IOPMSystemSleepParameters params;
5663 uint32_t hibMode = 0;
5664 bool ok;
5665
5666 if (gIOPMWorkLoop->inGate() == false) {
5667 IOReturn ret = gIOPMWorkLoop->runAction(
5668 OSMemberFunctionCast(IOWorkLoop::Action, this,
5669 &IOPMrootDomain::getSystemSleepType),
5670 (OSObject *) this,
5671 (void *) sleepType, (void *) standbyTimer);
5672 return ret;
5673 }
5674
5675 getSleepOption(kIOHibernateModeKey, &hibMode);
5676 bzero(¶ms, sizeof(params));
5677
5678 ok = evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase0, &hibMode);
5679 if (ok) {
5680 *sleepType = params.sleepType;
5681 if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5682 !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5683 DLOG("Standby delay is not set\n");
5684 *standbyTimer = 0;
5685 }
5686 return kIOReturnSuccess;
5687 }
5688 #endif
5689
5690 return kIOReturnUnsupported;
5691 }
5692
5693 // MARK: -
5694 // MARK: Shutdown and Restart
5695
5696 //******************************************************************************
5697 // handlePlatformHaltRestart
5698 //
5699 //******************************************************************************
5700
5701 // Phases while performing shutdown/restart
5702 typedef enum {
5703 kNotifyDone = 0x00,
5704 kNotifyPriorityClients = 0x10,
5705 kNotifyPowerPlaneDrivers = 0x20,
5706 kNotifyHaltRestartAction = 0x30,
5707 kQuiescePM = 0x40,
5708 } shutdownPhase_t;
5709
5710
5711 struct HaltRestartApplierContext {
5712 IOPMrootDomain * RootDomain;
5713 unsigned long PowerState;
5714 IOPMPowerFlags PowerFlags;
5715 UInt32 MessageType;
5716 UInt32 Counter;
5717 const char * LogString;
5718 shutdownPhase_t phase;
5719
5720 IOServiceInterestHandler handler;
5721 } gHaltRestartCtx;
5722
5723 const char *
5724 shutdownPhase2String(shutdownPhase_t phase)
5725 {
5726 switch (phase) {
5727 case kNotifyDone:
5728 return "Notifications completed";
5729 case kNotifyPriorityClients:
5730 return "Notifying priority clients";
5731 case kNotifyPowerPlaneDrivers:
5732 return "Notifying power plane drivers";
5733 case kNotifyHaltRestartAction:
5734 return "Notifying HaltRestart action handlers";
5735 case kQuiescePM:
5736 return "Quiescing PM";
5737 default:
5738 return "Unknown";
5739 }
5740 }
5741
5742 static void
5743 platformHaltRestartApplier( OSObject * object, void * context )
5744 {
5745 IOPowerStateChangeNotification notify;
5746 HaltRestartApplierContext * ctx;
5747 AbsoluteTime startTime, elapsedTime;
5748 uint32_t deltaTime;
5749
5750 ctx = (HaltRestartApplierContext *) context;
5751
5752 _IOServiceInterestNotifier * notifier;
5753 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5754 memset(¬ify, 0, sizeof(notify));
5755 notify.powerRef = (void *)(uintptr_t)ctx->Counter;
5756 notify.returnValue = 0;
5757 notify.stateNumber = ctx->PowerState;
5758 notify.stateFlags = ctx->PowerFlags;
5759
5760 if (notifier) {
5761 ctx->handler = notifier->handler;
5762 }
5763
5764 clock_get_uptime(&startTime);
5765 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)¬ify );
5766 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5767
5768 if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
5769 LOG("%s handler %p took %u ms\n",
5770 ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
5771 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
5772 }
5773
5774 ctx->handler = NULL;
5775 ctx->Counter++;
5776 }
5777
5778 static void
5779 quiescePowerTreeCallback( void * target, void * param )
5780 {
5781 IOLockLock(gPMHaltLock);
5782 gPMQuiesced = true;
5783 thread_wakeup(param);
5784 IOLockUnlock(gPMHaltLock);
5785 }
5786
5787 void
5788 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5789 {
5790 AbsoluteTime startTime, elapsedTime;
5791 uint32_t deltaTime;
5792 bool nvramSync = false;
5793
5794 memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5795 gHaltRestartCtx.RootDomain = this;
5796
5797 clock_get_uptime(&startTime);
5798 switch (pe_type) {
5799 case kPEHaltCPU:
5800 case kPEUPSDelayHaltCPU:
5801 gHaltRestartCtx.PowerState = OFF_STATE;
5802 gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5803 gHaltRestartCtx.LogString = "PowerOff";
5804 nvramSync = true;
5805 break;
5806
5807 case kPERestartCPU:
5808 gHaltRestartCtx.PowerState = RESTART_STATE;
5809 gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5810 gHaltRestartCtx.LogString = "Restart";
5811 nvramSync = true;
5812 break;
5813
5814 case kPEPagingOff:
5815 gHaltRestartCtx.PowerState = ON_STATE;
5816 gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5817 gHaltRestartCtx.LogString = "PagingOff";
5818 IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5819 #if HIBERNATION
5820 IOHibernateSystemRestart();
5821 #endif
5822 break;
5823
5824 default:
5825 return;
5826 }
5827
5828 if (nvramSync) {
5829 PESyncNVRAM();
5830 }
5831
5832 gHaltRestartCtx.phase = kNotifyPriorityClients;
5833 // Notify legacy clients
5834 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5835
5836 // For normal shutdown, turn off File Server Mode.
5837 if (kPEHaltCPU == pe_type) {
5838 OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
5839 OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32);
5840 if (setting && num) {
5841 setPMSetting(setting.get(), num.get());
5842 }
5843 }
5844
5845 if (kPEPagingOff != pe_type) {
5846 gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5847 // Notify in power tree order
5848 notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5849 }
5850
5851 gHaltRestartCtx.phase = kNotifyHaltRestartAction;
5852 #if defined(XNU_TARGET_OS_OSX)
5853 IOCPURunPlatformHaltRestartActions(pe_type);
5854 #else /* !defined(XNU_TARGET_OS_OSX) */
5855 if (kPEPagingOff != pe_type) {
5856 IOCPURunPlatformHaltRestartActions(pe_type);
5857 }
5858 #endif /* !defined(XNU_TARGET_OS_OSX) */
5859
5860 // Wait for PM to quiesce
5861 if ((kPEPagingOff != pe_type) && gPMHaltLock) {
5862 gHaltRestartCtx.phase = kQuiescePM;
5863 AbsoluteTime quiesceTime = mach_absolute_time();
5864
5865 IOLockLock(gPMHaltLock);
5866 gPMQuiesced = false;
5867 if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
5868 kIOReturnSuccess) {
5869 while (!gPMQuiesced) {
5870 IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
5871 }
5872 }
5873 IOLockUnlock(gPMHaltLock);
5874 deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
5875 DLOG("PM quiesce took %u ms\n", deltaTime);
5876 halt_log_enter("Quiesce", NULL, elapsedTime);
5877 }
5878 gHaltRestartCtx.phase = kNotifyDone;
5879
5880 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5881 LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5882
5883 halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
5884
5885 deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5886 LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5887
5888 if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
5889 printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
5890 }
5891
5892 checkShutdownTimeout();
5893 }
5894
5895 bool
5896 IOPMrootDomain::checkShutdownTimeout()
5897 {
5898 AbsoluteTime elapsedTime;
5899 uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5900
5901 if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
5902 return true;
5903 }
5904 return false;
5905 }
5906
5907 void
5908 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
5909 {
5910 if (gHaltLog) {
5911 if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
5912 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
5913 }
5914 panic("%s timed out in phase '%s'. Total %d ms:%s",
5915 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
5916 } else {
5917 panic("%s timed out in phase \'%s\'. Total %d ms",
5918 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
5919 }
5920 }
5921
5922 //******************************************************************************
5923 // shutdownSystem
5924 //
5925 //******************************************************************************
5926
5927 IOReturn
5928 IOPMrootDomain::shutdownSystem( void )
5929 {
5930 return kIOReturnUnsupported;
5931 }
5932
5933 //******************************************************************************
5934 // restartSystem
5935 //
5936 //******************************************************************************
5937
5938 IOReturn
5939 IOPMrootDomain::restartSystem( void )
5940 {
5941 return kIOReturnUnsupported;
5942 }
5943
5944 // MARK: -
5945 // MARK: System Capability
5946
5947 //******************************************************************************
5948 // tagPowerPlaneService
5949 //
5950 // Running on PM work loop thread.
5951 //******************************************************************************
5952
5953 void
5954 IOPMrootDomain::tagPowerPlaneService(
5955 IOService * service,
5956 IOPMActions * actions,
5957 IOPMPowerStateIndex maxPowerState )
5958 {
5959 uint32_t flags = 0;
5960
5961 memset(actions, 0, sizeof(*actions));
5962 actions->target = this;
5963
5964 if (service == this) {
5965 actions->actionPowerChangeStart =
5966 OSMemberFunctionCast(
5967 IOPMActionPowerChangeStart, this,
5968 &IOPMrootDomain::handleOurPowerChangeStart);
5969
5970 actions->actionPowerChangeDone =
5971 OSMemberFunctionCast(
5972 IOPMActionPowerChangeDone, this,
5973 &IOPMrootDomain::handleOurPowerChangeDone);
5974
5975 actions->actionPowerChangeOverride =
5976 OSMemberFunctionCast(
5977 IOPMActionPowerChangeOverride, this,
5978 &IOPMrootDomain::overrideOurPowerChange);
5979 return;
5980 }
5981
5982 #if DISPLAY_WRANGLER_PRESENT
5983 if (NULL != service->metaCast("IODisplayWrangler")) {
5984 // XXX should this really retain?
5985 wrangler.reset(service, OSRetain);
5986 wrangler->registerInterest(gIOGeneralInterest,
5987 &displayWranglerNotification, this, NULL);
5988
5989 // found the display wrangler, check for any display assertions already created
5990 if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
5991 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5992 wrangler->setIgnoreIdleTimer( true );
5993 }
5994 flags |= kPMActionsFlagIsDisplayWrangler;
5995 }
5996 #endif /* DISPLAY_WRANGLER_PRESENT */
5997
5998 if (service->propertyExists("IOPMStrictTreeOrder")) {
5999 flags |= kPMActionsFlagIsGraphicsDriver;
6000 }
6001 if (service->propertyExists("IOPMUnattendedWakePowerState")) {
6002 flags |= kPMActionsFlagIsAudioDriver;
6003 }
6004
6005 // Find the power connection object that is a child of the PCI host
6006 // bridge, and has a graphics/audio device attached below. Mark the
6007 // power branch for delayed child notifications.
6008
6009 if (flags) {
6010 IORegistryEntry * child = service;
6011 IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
6012
6013 while (child != this) {
6014 if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) {
6015 // Skip delaying notifications and clamping power on external graphics and audio devices.
6016 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
6017 flags = 0;
6018 break;
6019 }
6020 if ((parent == pciHostBridgeDriver) ||
6021 (parent == this)) {
6022 if (OSDynamicCast(IOPowerConnection, child)) {
6023 IOPowerConnection * conn = (IOPowerConnection *) child;
6024 conn->delayChildNotification = true;
6025 DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
6026 }
6027 break;
6028 }
6029 child = parent;
6030 parent = child->getParentEntry(gIOPowerPlane);
6031 }
6032 }
6033
6034 OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
6035 if (prop) {
6036 OSNumber * num = OSDynamicCast(OSNumber, prop.get());
6037 if (num) {
6038 actions->darkWakePowerState = num->unsigned32BitValue();
6039 if (actions->darkWakePowerState < maxPowerState) {
6040 flags |= kPMActionsFlagHasDarkWakePowerState;
6041 }
6042 }
6043 }
6044
6045
6046 if (flags) {
6047 DLOG("%s tag flags %x\n", service->getName(), flags);
6048 actions->flags |= flags;
6049 actions->actionPowerChangeOverride =
6050 OSMemberFunctionCast(
6051 IOPMActionPowerChangeOverride, this,
6052 &IOPMrootDomain::overridePowerChangeForService);
6053
6054 if (flags & kPMActionsFlagIsDisplayWrangler) {
6055 actions->actionActivityTickle =
6056 OSMemberFunctionCast(
6057 IOPMActionActivityTickle, this,
6058 &IOPMrootDomain::handleActivityTickleForDisplayWrangler);
6059
6060 actions->actionUpdatePowerClient =
6061 OSMemberFunctionCast(
6062 IOPMActionUpdatePowerClient, this,
6063 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
6064 }
6065 return;
6066 }
6067
6068 // Locate the first PCI host bridge for PMTrace.
6069 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
6070 IOService * provider = service->getProvider();
6071 if (OSDynamicCast(IOPlatformDevice, provider) &&
6072 provider->inPlane(gIODTPlane)) {
6073 pciHostBridgeDevice.reset(provider, OSNoRetain);
6074 pciHostBridgeDriver.reset(service, OSNoRetain);
6075 DLOG("PMTrace found PCI host bridge %s->%s\n",
6076 provider->getName(), service->getName());
6077 }
6078 }
6079
6080 // Tag top-level PCI devices. The order of PMinit() call does not
6081 // change across boots and is used as the PCI bit number.
6082 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
6083 // Would prefer to check built-in property, but tagPowerPlaneService()
6084 // is called before pciDevice->registerService().
6085 IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
6086 if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) {
6087 int bit = pmTracer->recordTopLevelPCIDevice( service );
6088 if (bit >= 0) {
6089 // Save the assigned bit for fast lookup.
6090 actions->flags |= (bit & kPMActionsPCIBitNumberMask);
6091
6092 actions->actionPowerChangeStart =
6093 OSMemberFunctionCast(
6094 IOPMActionPowerChangeStart, this,
6095 &IOPMrootDomain::handlePowerChangeStartForPCIDevice);
6096
6097 actions->actionPowerChangeDone =
6098 OSMemberFunctionCast(
6099 IOPMActionPowerChangeDone, this,
6100 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
6101 }
6102 }
6103 }
6104 }
6105
6106 //******************************************************************************
6107 // PM actions for root domain
6108 //******************************************************************************
6109
6110 void
6111 IOPMrootDomain::overrideOurPowerChange(
6112 IOService * service,
6113 IOPMActions * actions,
6114 const IOPMRequest * request,
6115 IOPMPowerStateIndex * inOutPowerState,
6116 IOPMPowerChangeFlags * inOutChangeFlags )
6117 {
6118 uint32_t changeFlags = *inOutChangeFlags;
6119 uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
6120 uint32_t currentPowerState = (uint32_t) getPowerState();
6121
6122 if (request->getTag() == 0) {
6123 // Set a tag for any request that originates from IOServicePM
6124 (const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
6125 }
6126
6127 DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6128 getPowerStateString(currentPowerState),
6129 getPowerStateString(desiredPowerState),
6130 _currentCapability, changeFlags,
6131 request->getTag());
6132
6133
6134 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6135 /*
6136 * ASBM send lowBattery notifications every 1 second until the device
6137 * enters hibernation. This queues up multiple sleep requests.
6138 * After the device wakes from hibernation, none of these previously
6139 * queued sleep requests are valid.
6140 * lowBattteryCondition variable is set when ASBM notifies rootDomain
6141 * and is cleared at the very last point in sleep.
6142 * Any attempt to sleep with reason kIOPMSleepReasonLowPower without
6143 * lowBatteryCondition is invalid
6144 */
6145 if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) {
6146 if (!lowBatteryCondition) {
6147 DLOG("Duplicate lowBattery sleep");
6148 *inOutChangeFlags |= kIOPMNotDone;
6149 return;
6150 }
6151 }
6152 #endif
6153
6154 if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
6155 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6156 *inOutChangeFlags |= kIOPMNotDone;
6157 return;
6158 }
6159
6160 if (changeFlags & kIOPMParentInitiated) {
6161 // Root parent is permanently pegged at max power,
6162 // a parent initiated power change is unexpected.
6163 *inOutChangeFlags |= kIOPMNotDone;
6164 return;
6165 }
6166
6167 #if HIBERNATION && defined(__arm64__)
6168 if (lowBatteryCondition && (desiredPowerState < currentPowerState)) {
6169 if (!ml_is_secure_hib_supported()) {
6170 // If hibernation is unsupported, reject sleep requests to avoid
6171 // racing with system shutdown.
6172 *inOutChangeFlags |= kIOPMNotDone;
6173 return;
6174 }
6175 }
6176 #endif /* HIBERNATION && defined(__arm64__) */
6177
6178 if (desiredPowerState < currentPowerState) {
6179 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6180 // Root domain is dropping power state from ON->SLEEP.
6181 // If system is in full wake, first enter dark wake by
6182 // converting the power drop to a capability change.
6183 // Once in dark wake, transition to sleep state ASAP.
6184
6185 darkWakeToSleepASAP = true;
6186
6187 // Drop graphics and audio capability
6188 _desiredCapability &= ~(
6189 kIOPMSystemCapabilityGraphics |
6190 kIOPMSystemCapabilityAudio);
6191
6192 // Convert to capability change (ON->ON)
6193 *inOutPowerState = getRUN_STATE();
6194 *inOutChangeFlags |= kIOPMSynchronize;
6195
6196 // Revert device desire from SLEEP to ON
6197 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6198 } else {
6199 // System is already in dark wake, ok to drop power state.
6200 // Broadcast root power down to entire tree.
6201 *inOutChangeFlags |= kIOPMRootChangeDown;
6202 }
6203 } else if (desiredPowerState > currentPowerState) {
6204 if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
6205 // Broadcast power up when waking from sleep, but not for the
6206 // initial power change at boot by checking for cpu capability.
6207 *inOutChangeFlags |= kIOPMRootChangeUp;
6208 }
6209 }
6210 }
6211
6212 void
6213 IOPMrootDomain::handleOurPowerChangeStart(
6214 IOService * service,
6215 IOPMActions * actions,
6216 const IOPMRequest * request,
6217 IOPMPowerStateIndex newPowerState,
6218 IOPMPowerChangeFlags * inOutChangeFlags )
6219 {
6220 IOPMRequestTag requestTag = request->getTag();
6221 IOPMRequestTag sleepReason;
6222
6223 uint32_t changeFlags = *inOutChangeFlags;
6224 uint32_t currentPowerState = (uint32_t) getPowerState();
6225 bool publishSleepReason = false;
6226
6227 // Check if request has a valid sleep reason
6228 sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6229 if (sleepReason < kIOPMSleepReasonClamshell) {
6230 sleepReason = kIOPMSleepReasonIdle;
6231 }
6232
6233 _systemTransitionType = kSystemTransitionNone;
6234 _systemMessageClientMask = 0;
6235 capabilityLoss = false;
6236 toldPowerdCapWillChange = false;
6237
6238 // Emergency notifications may arrive after the initial sleep request
6239 // has been queued. Override the sleep reason so powerd and others can
6240 // treat this as an emergency sleep.
6241 if (lowBatteryCondition) {
6242 sleepReason = kIOPMSleepReasonLowPower;
6243 } else if (thermalEmergencyState) {
6244 sleepReason = kIOPMSleepReasonThermalEmergency;
6245 }
6246
6247 // 1. Explicit capability change.
6248 if (changeFlags & kIOPMSynchronize) {
6249 if (newPowerState == ON_STATE) {
6250 if (changeFlags & kIOPMSyncNoChildNotify) {
6251 _systemTransitionType = kSystemTransitionNewCapClient;
6252 } else {
6253 _systemTransitionType = kSystemTransitionCapability;
6254 }
6255 }
6256 }
6257 // 2. Going to sleep (cancellation still possible).
6258 else if (newPowerState < currentPowerState) {
6259 _systemTransitionType = kSystemTransitionSleep;
6260 }
6261 // 3. Woke from (idle or demand) sleep.
6262 else if (!systemBooting &&
6263 (changeFlags & kIOPMSelfInitiated) &&
6264 (newPowerState > currentPowerState)) {
6265 _systemTransitionType = kSystemTransitionWake;
6266 _desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
6267
6268 // Early exit from dark wake to full (e.g. LID open)
6269 if (kFullWakeReasonNone != fullWakeReason) {
6270 _desiredCapability |= (
6271 kIOPMSystemCapabilityGraphics |
6272 kIOPMSystemCapabilityAudio);
6273
6274 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6275 if (fullWakeReason == kFullWakeReasonLocalUser) {
6276 darkWakeExit = true;
6277 darkWakeToSleepASAP = false;
6278 setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ?
6279 kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser);
6280 }
6281 #endif
6282 }
6283 #if HIBERNATION
6284 IOHibernateSetWakeCapabilities(_desiredCapability);
6285 #endif
6286 }
6287
6288 // Update pending wake capability at the beginning of every
6289 // state transition (including synchronize). This will become
6290 // the current capability at the end of the transition.
6291
6292 if (kSystemTransitionSleep == _systemTransitionType) {
6293 _pendingCapability = 0;
6294 capabilityLoss = true;
6295 } else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6296 _pendingCapability = _desiredCapability |
6297 kIOPMSystemCapabilityCPU |
6298 kIOPMSystemCapabilityNetwork;
6299
6300 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6301 _pendingCapability |= kIOPMSystemCapabilityAudio;
6302 }
6303
6304 if ((kSystemTransitionCapability == _systemTransitionType) &&
6305 (_pendingCapability == _currentCapability)) {
6306 // Cancel the PM state change.
6307 _systemTransitionType = kSystemTransitionNone;
6308 *inOutChangeFlags |= kIOPMNotDone;
6309 }
6310 if (__builtin_popcount(_pendingCapability) <
6311 __builtin_popcount(_currentCapability)) {
6312 capabilityLoss = true;
6313 }
6314 }
6315
6316 // 1. Capability change.
6317 if (kSystemTransitionCapability == _systemTransitionType) {
6318 // Dark to Full transition.
6319 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6320 tracePoint( kIOPMTracePointDarkWakeExit );
6321
6322 #if defined(XNU_TARGET_OS_OSX)
6323 // rdar://problem/65627936
6324 // When a dark->full wake promotion is scheduled before an ON->SLEEP
6325 // power state drop, invalidate any request to drop power state already
6326 // in the queue, including the override variant, unless full wake cannot
6327 // be sustained. Any power state drop queued after this SustainFullWake
6328 // request will not be affected.
6329 if (checkSystemCanSustainFullWake()) {
6330 changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake);
6331 }
6332 #endif
6333
6334 willEnterFullWake();
6335 }
6336
6337 // Full to Dark transition.
6338 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6339 // Clear previous stats
6340 IOLockLock(pmStatsLock);
6341 if (pmStatsAppResponses) {
6342 pmStatsAppResponses = OSArray::withCapacity(5);
6343 }
6344 IOLockUnlock(pmStatsLock);
6345
6346 tracePoint( kIOPMTracePointDarkWakeEntry );
6347 *inOutChangeFlags |= kIOPMSyncTellPowerDown;
6348 _systemMessageClientMask = kSystemMessageClientPowerd |
6349 kSystemMessageClientLegacyApp;
6350
6351 // rdar://15971327
6352 // Prevent user active transitions before notifying clients
6353 // that system will sleep.
6354 preventTransitionToUserActive(true);
6355
6356 IOService::setAdvisoryTickleEnable( false );
6357
6358 // Publish the sleep reason for full to dark wake
6359 publishSleepReason = true;
6360 lastSleepReason = fullToDarkReason = sleepReason;
6361
6362 // Publish a UUID for the Sleep --> Wake cycle
6363 handlePublishSleepWakeUUID(true);
6364 if (sleepDelaysReport) {
6365 clock_get_uptime(&ts_sleepStart);
6366 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
6367 }
6368
6369 darkWakeExit = false;
6370 }
6371 }
6372 // 2. System sleep.
6373 else if (kSystemTransitionSleep == _systemTransitionType) {
6374 // Beginning of a system sleep transition.
6375 // Cancellation is still possible.
6376 tracePoint( kIOPMTracePointSleepStarted );
6377
6378 _systemMessageClientMask = kSystemMessageClientAll;
6379 if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6380 _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6381 }
6382 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
6383 // Kernel priority clients are only notified on the initial
6384 // transition to full wake, so don't notify them unless system
6385 // has gained graphics capability since the last system wake.
6386 _systemMessageClientMask &= ~kSystemMessageClientKernel;
6387 } else {
6388 // System was in full wake, but the downwards power transition is driven
6389 // by a request that originates from IOServicePM, so it isn't tagged with
6390 // a valid system sleep reason.
6391 if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) {
6392 // Publish the same reason for full to dark
6393 sleepReason = fullToDarkReason;
6394 }
6395 }
6396 #if HIBERNATION
6397 gIOHibernateState = 0;
6398 #endif
6399
6400 // Record the reason for dark wake back to sleep
6401 // System may not have ever achieved full wake
6402
6403 publishSleepReason = true;
6404 lastSleepReason = sleepReason;
6405 if (sleepDelaysReport) {
6406 clock_get_uptime(&ts_sleepStart);
6407 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
6408 }
6409 }
6410 // 3. System wake.
6411 else if (kSystemTransitionWake == _systemTransitionType) {
6412 tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6413 // Clear stats about sleep
6414
6415 if (AOT_STATE == newPowerState) {
6416 _pendingCapability = 0;
6417 }
6418
6419 if (AOT_STATE == currentPowerState) {
6420 // Wake events are no longer accepted after waking to AOT_STATE.
6421 // Re-enable wake event acceptance to append wake events claimed
6422 // during the AOT to ON_STATE transition.
6423 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable);
6424 }
6425
6426 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6427 willEnterFullWake();
6428 }
6429 }
6430
6431 // The only location where the sleep reason is published. At this point
6432 // sleep can still be cancelled, but sleep reason should be published
6433 // early for logging purposes.
6434
6435 if (publishSleepReason) {
6436 static const char * IOPMSleepReasons[] =
6437 {
6438 kIOPMClamshellSleepKey,
6439 kIOPMPowerButtonSleepKey,
6440 kIOPMSoftwareSleepKey,
6441 kIOPMOSSwitchHibernationKey,
6442 kIOPMIdleSleepKey,
6443 kIOPMLowPowerSleepKey,
6444 kIOPMThermalEmergencySleepKey,
6445 kIOPMMaintenanceSleepKey,
6446 kIOPMSleepServiceExitKey,
6447 kIOPMDarkWakeThermalEmergencyKey,
6448 kIOPMNotificationWakeExitKey
6449 };
6450
6451 // Record sleep cause in IORegistry
6452 uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
6453 if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
6454 DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
6455 #if DEVELOPMENT || DEBUG
6456 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6457 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6458 "Sleep Reason", "%s\n", IOPMSleepReasons[reasonIndex]
6459 );
6460 #endif /* DEVELOPMENT || DEBUG */
6461 setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
6462 }
6463 }
6464
6465 if ((kSystemTransitionNone != _systemTransitionType) &&
6466 (kSystemTransitionNewCapClient != _systemTransitionType)) {
6467 _systemStateGeneration++;
6468 systemDarkWake = false;
6469
6470 DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6471 getPowerStateString(currentPowerState),
6472 getPowerStateString((uint32_t) newPowerState),
6473 _currentCapability, _pendingCapability,
6474 *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask,
6475 requestTag);
6476 #if DEVELOPMENT || DEBUG
6477 if (currentPowerState != (uint32_t) newPowerState) {
6478 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6479 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6480 "Start Power State Trans.",
6481 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6482 getPowerStateString(currentPowerState),
6483 getPowerStateString((uint32_t) newPowerState),
6484 _currentCapability,
6485 _pendingCapability,
6486 *inOutChangeFlags,
6487 _systemStateGeneration,
6488 _systemMessageClientMask,
6489 requestTag
6490 );
6491 }
6492 #endif /* DEVELOPMENT || DEBUG */
6493 }
6494
6495 if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6496 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6497 }
6498 if (_aotNow && (ON_STATE == newPowerState)) {
6499 WAKEEVENT_LOCK();
6500 aotShouldExit(true);
6501 WAKEEVENT_UNLOCK();
6502 aotExit(false);
6503 }
6504 }
6505
6506 void
6507 IOPMrootDomain::handleOurPowerChangeDone(
6508 IOService * service,
6509 IOPMActions * actions,
6510 const IOPMRequest * request,
6511 IOPMPowerStateIndex oldPowerState,
6512 IOPMPowerChangeFlags changeFlags )
6513 {
6514 if (kSystemTransitionNewCapClient == _systemTransitionType) {
6515 _systemTransitionType = kSystemTransitionNone;
6516 return;
6517 }
6518
6519 if (_systemTransitionType != kSystemTransitionNone) {
6520 uint32_t currentPowerState = (uint32_t) getPowerState();
6521
6522 if (changeFlags & kIOPMNotDone) {
6523 // Power down was cancelled or vetoed.
6524 _pendingCapability = _currentCapability;
6525 lastSleepReason = 0;
6526
6527 // When sleep is cancelled or reverted, don't report
6528 // the target (lower) power state as the previous state.
6529 oldPowerState = currentPowerState;
6530
6531 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
6532 CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
6533 #if defined(XNU_TARGET_OS_OSX)
6534 pmPowerStateQueue->submitPowerEvent(
6535 kPowerEventPolicyStimulus,
6536 (void *) kStimulusDarkWakeReentry,
6537 _systemStateGeneration );
6538 #else /* !defined(XNU_TARGET_OS_OSX) */
6539 // On embedded, there are no factors that can prolong a
6540 // "darkWake" when a power down is vetoed. We need to
6541 // promote to "fullWake" at least once so that factors
6542 // that prevent idle sleep can assert themselves if required
6543 pmPowerStateQueue->submitPowerEvent(
6544 kPowerEventPolicyStimulus,
6545 (void *) kStimulusDarkWakeActivityTickle);
6546 #endif /* !defined(XNU_TARGET_OS_OSX) */
6547 }
6548
6549 // Revert device desire to max.
6550 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6551 } else {
6552 // Send message on dark wake to full wake promotion.
6553 // tellChangeUp() handles the normal SLEEP->ON case.
6554
6555 if (kSystemTransitionCapability == _systemTransitionType) {
6556 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6557 lastSleepReason = 0; // stop logging wrangler tickles
6558 tellClients(kIOMessageSystemHasPoweredOn);
6559 }
6560 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6561 // Going dark, reset full wake state
6562 // userIsActive will be cleared by wrangler powering down
6563 fullWakeReason = kFullWakeReasonNone;
6564
6565 if (ts_sleepStart) {
6566 clock_get_uptime(&wake2DarkwakeDelay);
6567 SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
6568 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
6569 ts_sleepStart = 0;
6570 }
6571 }
6572 }
6573
6574 // Reset state after exiting from dark wake.
6575
6576 if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6577 CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6578 darkWakeMaintenance = false;
6579 darkWakeToSleepASAP = false;
6580 pciCantSleepValid = false;
6581 darkWakeSleepService = false;
6582
6583 if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6584 // Remove the influence of display power assertion
6585 // before next system wake.
6586 if (wrangler) {
6587 wrangler->changePowerStateForRootDomain(
6588 kWranglerPowerStateMin );
6589 }
6590 removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6591 }
6592 }
6593
6594 // Entered dark mode.
6595
6596 if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6597 (_pendingCapability & kIOPMSystemCapabilityCPU)) {
6598 // Queue an evaluation of whether to remain in dark wake,
6599 // and for how long. This serves the purpose of draining
6600 // any assertions from the queue.
6601
6602 pmPowerStateQueue->submitPowerEvent(
6603 kPowerEventPolicyStimulus,
6604 (void *) kStimulusDarkWakeEntry,
6605 _systemStateGeneration );
6606 }
6607 }
6608
6609 #if DEVELOPMENT || DEBUG
6610 if (currentPowerState != (uint32_t) oldPowerState) {
6611 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6612 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6613 "Finish Power State Trans.",
6614 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6615 getPowerStateString((uint32_t)oldPowerState),
6616 getPowerStateString(currentPowerState),
6617 _currentCapability,
6618 _pendingCapability,
6619 changeFlags,
6620 _systemStateGeneration,
6621 _systemMessageClientMask,
6622 request->getTag()
6623 );
6624 }
6625 #endif /* DEVELOPMENT || DEBUG */
6626
6627 DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6628 getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState),
6629 _currentCapability, _pendingCapability,
6630 changeFlags, _systemStateGeneration, _systemMessageClientMask,
6631 request->getTag());
6632
6633 if ((currentPowerState == ON_STATE) && pmAssertions) {
6634 pmAssertions->reportCPUBitAccounting();
6635 }
6636
6637 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6638 displayWakeCnt++;
6639 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6640 if (clamshellExists && fullWakeThreadCall) {
6641 AbsoluteTime deadline;
6642 clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline);
6643 thread_call_enter_delayed(fullWakeThreadCall, deadline);
6644 }
6645 #endif
6646 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6647 darkWakeCnt++;
6648 }
6649
6650 // Update current system capability.
6651 if (_currentCapability != _pendingCapability) {
6652 _currentCapability = _pendingCapability;
6653 }
6654
6655 // Update highest system capability.
6656
6657 _highestCapability |= _currentCapability;
6658
6659 if (darkWakePostTickle &&
6660 (kSystemTransitionWake == _systemTransitionType) &&
6661 (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6662 kDarkWakeFlagPromotionLate) {
6663 darkWakePostTickle = false;
6664 reportUserInput();
6665 } else if (darkWakeExit) {
6666 requestFullWake( kFullWakeReasonLocalUser );
6667 }
6668
6669 // Reset tracepoint at completion of capability change,
6670 // completion of wake transition, and aborted sleep transition.
6671
6672 if ((_systemTransitionType == kSystemTransitionCapability) ||
6673 (_systemTransitionType == kSystemTransitionWake) ||
6674 ((_systemTransitionType == kSystemTransitionSleep) &&
6675 (changeFlags & kIOPMNotDone))) {
6676 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6677 tracePoint( kIOPMTracePointSystemUp );
6678 }
6679
6680 _systemTransitionType = kSystemTransitionNone;
6681 _systemMessageClientMask = 0;
6682 toldPowerdCapWillChange = false;
6683
6684 darkWakeLogClamp = false;
6685
6686 if (lowBatteryCondition) {
6687 privateSleepSystem(kIOPMSleepReasonLowPower);
6688 } else if (thermalEmergencyState) {
6689 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6690 } else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) {
6691 // Request for full wake is removed while system is waking up to full wake
6692 DLOG("DisplayOn fullwake request is removed\n");
6693 handleSetDisplayPowerOn(false);
6694 }
6695
6696 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6697 pmPowerStateQueue->submitPowerEvent(
6698 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6699 }
6700 }
6701 }
6702
6703 //******************************************************************************
6704 // PM actions for graphics and audio.
6705 //******************************************************************************
6706
6707 void
6708 IOPMrootDomain::overridePowerChangeForService(
6709 IOService * service,
6710 IOPMActions * actions,
6711 const IOPMRequest * request,
6712 IOPMPowerStateIndex * inOutPowerState,
6713 IOPMPowerChangeFlags * inOutChangeFlags )
6714 {
6715 uint32_t powerState = (uint32_t) *inOutPowerState;
6716 uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6717 const uint32_t actionFlags = actions->flags;
6718
6719 if (kSystemTransitionNone == _systemTransitionType) {
6720 // Not in midst of a system transition.
6721 // Do not set kPMActionsStatePowerClamped.
6722 } else if ((actions->state & kPMActionsStatePowerClamped) == 0) {
6723 bool enableClamp = false;
6724
6725 // For most drivers, enable the clamp during ON->Dark transition
6726 // which has the kIOPMSynchronize flag set in changeFlags.
6727 if ((actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6728 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6729 (changeFlags & kIOPMSynchronize)) {
6730 enableClamp = true;
6731 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6732 ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6733 ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6734 (changeFlags & kIOPMSynchronize)) {
6735 enableClamp = true;
6736 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6737 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6738 (changeFlags & kIOPMSynchronize)) {
6739 enableClamp = true;
6740 } else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) &&
6741 (_systemTransitionType == kSystemTransitionSleep)) {
6742 // For graphics drivers, clamp power when entering
6743 // system sleep. Not when dropping to dark wake.
6744 enableClamp = true;
6745 }
6746
6747 if (enableClamp) {
6748 actions->state |= kPMActionsStatePowerClamped;
6749 DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6750 service->getName(), service->getRegistryEntryID(),
6751 _pendingCapability, powerState, changeFlags);
6752 }
6753 } else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6754 bool disableClamp = false;
6755
6756 if ((actionFlags & (
6757 kPMActionsFlagIsDisplayWrangler |
6758 kPMActionsFlagIsGraphicsDriver)) &&
6759 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6760 disableClamp = true;
6761 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6762 (_pendingCapability & kIOPMSystemCapabilityAudio)) {
6763 disableClamp = true;
6764 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6765 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6766 disableClamp = true;
6767 }
6768
6769 if (disableClamp) {
6770 actions->state &= ~kPMActionsStatePowerClamped;
6771 DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6772 service->getName(), service->getRegistryEntryID(),
6773 _pendingCapability, powerState, changeFlags);
6774 }
6775 }
6776
6777 if (actions->state & kPMActionsStatePowerClamped) {
6778 uint32_t maxPowerState = 0;
6779
6780 // Determine the max power state allowed when clamp is enabled
6781 if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
6782 // Parent intiated power state changes
6783 if ((service->getPowerState() > maxPowerState) &&
6784 (actionFlags & kPMActionsFlagIsDisplayWrangler)) {
6785 maxPowerState++;
6786
6787 // Remove lingering effects of any tickle before entering
6788 // dark wake. It will take a new tickle to return to full
6789 // wake, so the existing tickle state is useless.
6790
6791 if (changeFlags & kIOPMDomainDidChange) {
6792 *inOutChangeFlags |= kIOPMExpireIdleTimer;
6793 }
6794 } else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6795 maxPowerState++;
6796 } else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6797 maxPowerState = actions->darkWakePowerState;
6798 }
6799 } else {
6800 // Deny all self-initiated changes when power is limited.
6801 // Wrangler tickle should never defeat the limiter.
6802 maxPowerState = service->getPowerState();
6803 }
6804
6805 if (powerState > maxPowerState) {
6806 DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6807 service->getName(), service->getRegistryEntryID(),
6808 powerState, maxPowerState, changeFlags);
6809 *inOutPowerState = maxPowerState;
6810
6811 if (darkWakePostTickle &&
6812 (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6813 (changeFlags & kIOPMDomainWillChange) &&
6814 ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6815 kDarkWakeFlagPromotionEarly)) {
6816 darkWakePostTickle = false;
6817 reportUserInput();
6818 }
6819 }
6820
6821 if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
6822 if (darkWakeLogClamp) {
6823 AbsoluteTime now;
6824 uint64_t nsec;
6825
6826 clock_get_uptime(&now);
6827 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
6828 absolutetime_to_nanoseconds(now, &nsec);
6829 DLOG("dark wake power clamped after %u ms\n",
6830 ((int)((nsec) / NSEC_PER_MSEC)));
6831 }
6832 darkWakePowerClamped = true;
6833 }
6834 }
6835 }
6836
6837 void
6838 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6839 IOService * service,
6840 IOPMActions * actions )
6841 {
6842 #if DISPLAY_WRANGLER_PRESENT
6843 // Warning: Not running in PM work loop context - don't modify state !!!
6844 // Trap tickle directed to IODisplayWrangler while running with graphics
6845 // capability suppressed.
6846
6847 assert(service == wrangler);
6848
6849 clock_get_uptime(&userActivityTime);
6850 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
6851 || (lastSleepReason == kIOPMSleepReasonMaintenance)
6852 || (lastSleepReason == kIOPMSleepReasonSoftware));
6853 if (aborting) {
6854 userActivityCount++;
6855 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6856 userActivityCount, lastSleepReason);
6857 }
6858
6859 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
6860 DLOG("display wrangler tickled\n");
6861 if (kIOLogPMRootDomain & gIOKitDebug) {
6862 OSReportWithBacktrace("Dark wake display tickle");
6863 }
6864 if (pmPowerStateQueue) {
6865 pmPowerStateQueue->submitPowerEvent(
6866 kPowerEventPolicyStimulus,
6867 (void *) kStimulusDarkWakeActivityTickle,
6868 true /* set wake type */ );
6869 }
6870 }
6871 #endif /* DISPLAY_WRANGLER_PRESENT */
6872 }
6873
6874 void
6875 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6876 IOService * service,
6877 IOPMActions * actions,
6878 const OSSymbol * powerClient,
6879 IOPMPowerStateIndex oldPowerState,
6880 IOPMPowerStateIndex newPowerState )
6881 {
6882 #if DISPLAY_WRANGLER_PRESENT
6883 assert(service == wrangler);
6884
6885 // This function implements half of the user active detection
6886 // by monitoring changes to the display wrangler's device desire.
6887 //
6888 // User becomes active when either:
6889 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6890 // in max power state. This desire change in absence of a power state
6891 // change is detected within. This handles the case when user becomes
6892 // active while the display is already lit by setDisplayPowerOn().
6893 //
6894 // 2. Power state change to max, and DeviceDesire is also at max.
6895 // Handled by displayWranglerNotification().
6896 //
6897 // User becomes inactive when DeviceDesire drops to sleep state or below.
6898
6899 DLOG("wrangler %s (ps %u, %u->%u)\n",
6900 powerClient->getCStringNoCopy(),
6901 (uint32_t) service->getPowerState(),
6902 (uint32_t) oldPowerState, (uint32_t) newPowerState);
6903
6904 if (powerClient == gIOPMPowerClientDevice) {
6905 if ((newPowerState > oldPowerState) &&
6906 (newPowerState == kWranglerPowerStateMax) &&
6907 (service->getPowerState() == kWranglerPowerStateMax)) {
6908 evaluatePolicy( kStimulusEnterUserActiveState );
6909 } else if ((newPowerState < oldPowerState) &&
6910 (newPowerState <= kWranglerPowerStateSleep)) {
6911 evaluatePolicy( kStimulusLeaveUserActiveState );
6912 }
6913 }
6914
6915 if (newPowerState <= kWranglerPowerStateSleep) {
6916 evaluatePolicy( kStimulusDisplayWranglerSleep );
6917 } else if (newPowerState == kWranglerPowerStateMax) {
6918 evaluatePolicy( kStimulusDisplayWranglerWake );
6919 }
6920 #endif /* DISPLAY_WRANGLER_PRESENT */
6921 }
6922
6923 //******************************************************************************
6924 // User active state management
6925 //******************************************************************************
6926
6927 void
6928 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
6929 {
6930 #if DISPLAY_WRANGLER_PRESENT
6931 _preventUserActive = prevent;
6932 if (wrangler && !_preventUserActive) {
6933 // Allowing transition to user active, but the wrangler may have
6934 // already powered ON in case of sleep cancel/revert. Poll the
6935 // same conditions checked for in displayWranglerNotification()
6936 // to bring the user active state up to date.
6937
6938 if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
6939 (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
6940 kWranglerPowerStateMax)) {
6941 evaluatePolicy( kStimulusEnterUserActiveState );
6942 }
6943 }
6944 #endif /* DISPLAY_WRANGLER_PRESENT */
6945 }
6946
6947 //******************************************************************************
6948 // Approve usage of delayed child notification by PM.
6949 //******************************************************************************
6950
6951 bool
6952 IOPMrootDomain::shouldDelayChildNotification(
6953 IOService * service )
6954 {
6955 if ((kFullWakeReasonNone == fullWakeReason) &&
6956 (kSystemTransitionWake == _systemTransitionType)) {
6957 DLOG("%s: delay child notify\n", service->getName());
6958 return true;
6959 }
6960 return false;
6961 }
6962
6963 //******************************************************************************
6964 // PM actions for PCI device.
6965 //******************************************************************************
6966
6967 void
6968 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6969 IOService * service,
6970 IOPMActions * actions,
6971 const IOPMRequest * request,
6972 IOPMPowerStateIndex powerState,
6973 IOPMPowerChangeFlags * inOutChangeFlags )
6974 {
6975 pmTracer->tracePCIPowerChange(
6976 PMTraceWorker::kPowerChangeStart,
6977 service, *inOutChangeFlags,
6978 (actions->flags & kPMActionsPCIBitNumberMask));
6979 }
6980
6981 void
6982 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6983 IOService * service,
6984 IOPMActions * actions,
6985 const IOPMRequest * request,
6986 IOPMPowerStateIndex powerState,
6987 IOPMPowerChangeFlags changeFlags )
6988 {
6989 pmTracer->tracePCIPowerChange(
6990 PMTraceWorker::kPowerChangeCompleted,
6991 service, changeFlags,
6992 (actions->flags & kPMActionsPCIBitNumberMask));
6993 }
6994
6995 //******************************************************************************
6996 // registerInterest
6997 //
6998 // Override IOService::registerInterest() for root domain clients.
6999 //******************************************************************************
7000
7001 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
7002 {
7003 friend class IOPMrootDomain;
7004 OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
7005
7006 protected:
7007 uint32_t ackTimeoutCnt;
7008 uint32_t msgType; // Last type seen by the message filter
7009 uint32_t lastSleepWakeMsgType;
7010 uint32_t msgIndex;
7011 uint32_t maxMsgDelayMS;
7012 uint32_t maxAckDelayMS;
7013 uint64_t msgAbsTime;
7014 uint64_t uuid0;
7015 uint64_t uuid1;
7016 OSSharedPtr<const OSSymbol> identifier;
7017 OSSharedPtr<const OSSymbol> clientName;
7018 };
7019
7020 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
7021
7022 OSSharedPtr<IONotifier>
7023 IOPMrootDomain::registerInterest(
7024 const OSSymbol * typeOfInterest,
7025 IOServiceInterestHandler handler,
7026 void * target, void * ref )
7027 {
7028 IOPMServiceInterestNotifier* notifier;
7029 bool isSystemCapabilityClient;
7030 bool isKernelCapabilityClient;
7031 IOReturn rc = kIOReturnError;
7032
7033 isSystemCapabilityClient = typeOfInterest &&
7034 typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
7035
7036 isKernelCapabilityClient = typeOfInterest &&
7037 typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
7038
7039 if (isSystemCapabilityClient) {
7040 typeOfInterest = gIOAppPowerStateInterest;
7041 }
7042
7043 notifier = new IOPMServiceInterestNotifier;
7044 if (!notifier) {
7045 return NULL;
7046 }
7047
7048 if (notifier->init()) {
7049 rc = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
7050 }
7051 if (rc != kIOReturnSuccess) {
7052 OSSafeReleaseNULL(notifier);
7053 return NULL;
7054 }
7055
7056 notifier->ackTimeoutCnt = 0;
7057
7058 if (pmPowerStateQueue) {
7059 if (isSystemCapabilityClient) {
7060 notifier->retain();
7061 if (pmPowerStateQueue->submitPowerEvent(
7062 kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
7063 notifier->release();
7064 }
7065 }
7066
7067 if (isKernelCapabilityClient) {
7068 notifier->retain();
7069 if (pmPowerStateQueue->submitPowerEvent(
7070 kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
7071 notifier->release();
7072 }
7073 }
7074 }
7075
7076 OSSharedPtr<OSData> data;
7077 uint8_t *uuid = NULL;
7078 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
7079 if (kext) {
7080 data = kext->copyUUID();
7081 }
7082 if (data && (data->getLength() == sizeof(uuid_t))) {
7083 uuid = (uint8_t *)(data->getBytesNoCopy());
7084
7085 notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
7086 ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
7087 ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
7088 notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
7089 ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
7090 ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
7091
7092 notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
7093 }
7094 return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
7095 }
7096
7097 //******************************************************************************
7098 // systemMessageFilter
7099 //
7100 //******************************************************************************
7101
7102 bool
7103 IOPMrootDomain::systemMessageFilter(
7104 void * object, void * arg1, void * arg2, void * arg3 )
7105 {
7106 const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
7107 bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
7108 bool isCapPowerd = (object == (void *) systemCapabilityNotifier.get());
7109 bool isCapClient = false;
7110 bool allow = false;
7111 OSBoolean **waitForReply = (typeof(waitForReply))arg3;
7112 IOPMServiceInterestNotifier *notifier;
7113
7114 notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
7115
7116 do {
7117 // When powerd and kernel priority clients register capability interest,
7118 // the power tree is sync'ed to inform those clients about the current
7119 // system capability. Only allow capability change messages during sync.
7120 if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
7121 (!isCapMsg || !_joinedCapabilityClients ||
7122 !_joinedCapabilityClients->containsObject((OSObject *) object))) {
7123 break;
7124 }
7125
7126 // Capability change message for powerd and kernel clients
7127 if (isCapMsg) {
7128 // Kernel priority clients
7129 if ((context->notifyType == kNotifyPriority) ||
7130 (context->notifyType == kNotifyCapabilityChangePriority)) {
7131 isCapClient = true;
7132 }
7133
7134 // powerd will maintain two client registrations with root domain.
7135 // isCapPowerd will be TRUE for any message targeting the powerd
7136 // exclusive (capability change) interest registration.
7137 if (isCapPowerd && (context->notifyType == kNotifyCapabilityChangeApps)) {
7138 isCapClient = true;
7139 }
7140 }
7141
7142 if (isCapClient) {
7143 IOPMSystemCapabilityChangeParameters * capArgs =
7144 (IOPMSystemCapabilityChangeParameters *) arg2;
7145
7146 if (kSystemTransitionNewCapClient == _systemTransitionType) {
7147 capArgs->fromCapabilities = 0;
7148 capArgs->toCapabilities = _currentCapability;
7149 capArgs->changeFlags = 0;
7150 } else {
7151 capArgs->fromCapabilities = _currentCapability;
7152 capArgs->toCapabilities = _pendingCapability;
7153
7154 if (context->isPreChange) {
7155 capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
7156 } else {
7157 capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
7158 }
7159
7160 if (isCapPowerd && context->isPreChange) {
7161 toldPowerdCapWillChange = true;
7162 }
7163 }
7164
7165 // App level capability change messages must only go to powerd.
7166 // Wait for response post-change if capabilitiy is increasing.
7167 // Wait for response pre-change if capability is decreasing.
7168
7169 if ((context->notifyType == kNotifyCapabilityChangeApps) && waitForReply &&
7170 ((capabilityLoss && context->isPreChange) ||
7171 (!capabilityLoss && !context->isPreChange))) {
7172 *waitForReply = kOSBooleanTrue;
7173 }
7174
7175 allow = true;
7176 break;
7177 }
7178
7179 // powerd will always receive CanSystemSleep, even for a demand sleep.
7180 // It will also have a final chance to veto sleep after all clients
7181 // have responded to SystemWillSleep
7182
7183 if ((kIOMessageCanSystemSleep == context->messageType) ||
7184 (kIOMessageSystemWillNotSleep == context->messageType)) {
7185 if (isCapPowerd) {
7186 allow = true;
7187 break;
7188 }
7189
7190 // Demand sleep, don't ask apps for permission
7191 if (context->changeFlags & kIOPMSkipAskPowerDown) {
7192 break;
7193 }
7194 }
7195
7196 if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
7197 if (isCapPowerd && CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
7198 (fullToDarkReason == kIOPMSleepReasonIdle)) {
7199 allow = true;
7200 }
7201 break;
7202 }
7203
7204 // Drop capability change messages for legacy clients.
7205 // Drop legacy system sleep messages for powerd capability interest.
7206 if (isCapMsg || isCapPowerd) {
7207 break;
7208 }
7209
7210 // Not a capability change message.
7211 // Perform message filtering based on _systemMessageClientMask.
7212
7213 if ((context->notifyType == kNotifyApps) &&
7214 (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7215 if (!notifier) {
7216 break;
7217 }
7218
7219 if ((notifier->lastSleepWakeMsgType == context->messageType) &&
7220 (notifier->lastSleepWakeMsgType == kIOMessageSystemWillPowerOn)) {
7221 break; // drop any duplicate WillPowerOn for AOT devices
7222 }
7223
7224 allow = true;
7225
7226 if (waitForReply) {
7227 if (notifier->ackTimeoutCnt >= 3) {
7228 *waitForReply = kOSBooleanFalse;
7229 } else {
7230 *waitForReply = kOSBooleanTrue;
7231 }
7232 }
7233 } else if ((context->notifyType == kNotifyPriority) &&
7234 (_systemMessageClientMask & kSystemMessageClientKernel)) {
7235 allow = true;
7236 }
7237
7238 // Check sleep/wake message ordering
7239 if (allow) {
7240 if (context->messageType == kIOMessageSystemWillSleep ||
7241 context->messageType == kIOMessageSystemWillPowerOn ||
7242 context->messageType == kIOMessageSystemHasPoweredOn) {
7243 notifier->lastSleepWakeMsgType = context->messageType;
7244 }
7245 }
7246 } while (false);
7247
7248 if (allow && isCapMsg && _joinedCapabilityClients) {
7249 _joinedCapabilityClients->removeObject((OSObject *) object);
7250 if (_joinedCapabilityClients->getCount() == 0) {
7251 DMSG("destroyed capability client set %p\n",
7252 OBFUSCATE(_joinedCapabilityClients.get()));
7253 _joinedCapabilityClients.reset();
7254 }
7255 }
7256 if (notifier) {
7257 // Record the last seen message type even if the message is dropped
7258 // for traceFilteredNotification().
7259 notifier->msgType = context->messageType;
7260 }
7261
7262 return allow;
7263 }
7264
7265 //******************************************************************************
7266 // setMaintenanceWakeCalendar
7267 //
7268 //******************************************************************************
7269
7270 IOReturn
7271 IOPMrootDomain::setMaintenanceWakeCalendar(
7272 const IOPMCalendarStruct * calendar )
7273 {
7274 OSSharedPtr<OSData> data;
7275 IOReturn ret = 0;
7276
7277 if (!calendar) {
7278 return kIOReturnBadArgument;
7279 }
7280
7281 data = OSData::withValue(*calendar);
7282 if (!data) {
7283 return kIOReturnNoMemory;
7284 }
7285
7286 if (kPMCalendarTypeMaintenance == calendar->selector) {
7287 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get());
7288 } else if (kPMCalendarTypeSleepService == calendar->selector) {
7289 ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get());
7290 }
7291
7292 return ret;
7293 }
7294
7295 // MARK: -
7296 // MARK: Display Wrangler
7297
7298 //******************************************************************************
7299 // displayWranglerNotification
7300 //
7301 // Handle the notification when the IODisplayWrangler changes power state.
7302 //******************************************************************************
7303
7304 IOReturn
7305 IOPMrootDomain::displayWranglerNotification(
7306 void * target, void * refCon,
7307 UInt32 messageType, IOService * service,
7308 void * messageArgument, vm_size_t argSize )
7309 {
7310 #if DISPLAY_WRANGLER_PRESENT
7311 IOPMPowerStateIndex displayPowerState;
7312 IOPowerStateChangeNotification * params =
7313 (IOPowerStateChangeNotification *) messageArgument;
7314
7315 if ((messageType != kIOMessageDeviceWillPowerOff) &&
7316 (messageType != kIOMessageDeviceHasPoweredOn)) {
7317 return kIOReturnUnsupported;
7318 }
7319
7320 ASSERT_GATED();
7321 if (!gRootDomain) {
7322 return kIOReturnUnsupported;
7323 }
7324
7325 displayPowerState = params->stateNumber;
7326 DLOG("wrangler %s ps %d\n",
7327 getIOMessageString(messageType), (uint32_t) displayPowerState);
7328
7329 switch (messageType) {
7330 case kIOMessageDeviceWillPowerOff:
7331 // Display wrangler has dropped power due to display idle
7332 // or force system sleep.
7333 //
7334 // 4 Display ON kWranglerPowerStateMax
7335 // 3 Display Dim kWranglerPowerStateDim
7336 // 2 Display Sleep kWranglerPowerStateSleep
7337 // 1 Not visible to user
7338 // 0 Not visible to user kWranglerPowerStateMin
7339
7340 if (displayPowerState <= kWranglerPowerStateSleep) {
7341 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7342 }
7343 break;
7344
7345 case kIOMessageDeviceHasPoweredOn:
7346 // Display wrangler has powered on due to user activity
7347 // or wake from sleep.
7348
7349 if (kWranglerPowerStateMax == displayPowerState) {
7350 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7351
7352 // See comment in handleUpdatePowerClientForDisplayWrangler
7353 if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7354 kWranglerPowerStateMax) {
7355 gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7356 }
7357 }
7358 break;
7359 }
7360 #endif /* DISPLAY_WRANGLER_PRESENT */
7361 return kIOReturnUnsupported;
7362 }
7363
7364 //******************************************************************************
7365 // reportUserInput
7366 //
7367 //******************************************************************************
7368
7369 void
7370 IOPMrootDomain::updateUserActivity( void )
7371 {
7372 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7373 clock_get_uptime(&userActivityTime);
7374 bool aborting = ((lastSleepReason == kIOPMSleepReasonSoftware)
7375 || (lastSleepReason == kIOPMSleepReasonIdle)
7376 || (lastSleepReason == kIOPMSleepReasonMaintenance));
7377 if (aborting) {
7378 userActivityCount++;
7379 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7380 }
7381 #endif
7382 }
7383 void
7384 IOPMrootDomain::reportUserInput( void )
7385 {
7386 if (wrangler) {
7387 wrangler->activityTickle(0, 0);
7388 }
7389 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7390 // Update user activity
7391 updateUserActivity();
7392
7393 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7394 // update user active abs time
7395 clock_get_uptime(&gUserActiveAbsTime);
7396 pmPowerStateQueue->submitPowerEvent(
7397 kPowerEventPolicyStimulus,
7398 (void *) kStimulusDarkWakeActivityTickle,
7399 true /* set wake type */ );
7400 }
7401 #endif
7402 }
7403
7404 void
7405 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7406 {
7407 #if DISPLAY_WRANGLER_PRESENT
7408 if (wrangler) {
7409 wrangler->activityTickle(0, 0);
7410 }
7411 #else
7412 if (!device) {
7413 DLOG("requestUserActive: device is null\n");
7414 return;
7415 }
7416 OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7417 uint64_t registryID = device->getRegistryEntryID();
7418
7419 if (!deviceName || !registryID) {
7420 DLOG("requestUserActive: no device name or registry entry\n");
7421 return;
7422 }
7423 const char *name = deviceName->getCStringNoCopy();
7424 char payload[128];
7425 snprintf(payload, sizeof(payload), "%s:%s", name, reason);
7426 DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason);
7427 messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload));
7428 #endif
7429 }
7430
7431 //******************************************************************************
7432 // latchDisplayWranglerTickle
7433 //******************************************************************************
7434
7435 bool
7436 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7437 {
7438 #if DISPLAY_WRANGLER_PRESENT
7439 if (latch) {
7440 if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
7441 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7442 !checkSystemCanSustainFullWake()) {
7443 // Currently in dark wake, and not transitioning to full wake.
7444 // Full wake is unsustainable, so latch the tickle to prevent
7445 // the display from lighting up momentarily.
7446 wranglerTickled = true;
7447 } else {
7448 wranglerTickled = false;
7449 }
7450 } else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7451 wranglerTickled = false;
7452
7453 pmPowerStateQueue->submitPowerEvent(
7454 kPowerEventPolicyStimulus,
7455 (void *) kStimulusDarkWakeActivityTickle );
7456 }
7457
7458 return wranglerTickled;
7459 #else /* ! DISPLAY_WRANGLER_PRESENT */
7460 return false;
7461 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7462 }
7463
7464 //******************************************************************************
7465 // setDisplayPowerOn
7466 //
7467 // For root domain user client
7468 //******************************************************************************
7469
7470 void
7471 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7472 {
7473 pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7474 (void *) NULL, options );
7475 }
7476
7477 // MARK: -
7478 // MARK: System PM Policy
7479
7480 //******************************************************************************
7481 // checkSystemSleepAllowed
7482 //
7483 //******************************************************************************
7484
7485 bool
7486 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7487 uint32_t sleepReason )
7488 {
7489 uint32_t err = 0;
7490
7491 // Conditions that prevent idle and demand system sleep.
7492
7493 do {
7494 if (gSleepDisabledFlag) {
7495 err = kPMConfigPreventSystemSleep;
7496 break;
7497 }
7498
7499 if (userDisabledAllSleep) {
7500 err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7501 break;
7502 }
7503
7504 if (systemBooting || systemShutdown || gWillShutdown) {
7505 err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7506 break;
7507 }
7508
7509 if (options == 0) {
7510 break;
7511 }
7512
7513 // Conditions above pegs the system at full wake.
7514 // Conditions below prevent system sleep but does not prevent
7515 // dark wake, and must be called from gated context.
7516
7517 #if !CONFIG_SLEEP
7518 err = kPMConfigPreventSystemSleep; // 3. config does not support sleep
7519 break;
7520 #endif
7521
7522 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7523 break; // always sleep on low battery or when in thermal warning/emergency state
7524 }
7525
7526 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7527 break; // always sleep on dark wake thermal emergencies
7528 }
7529
7530 if (preventSystemSleepList->getCount() != 0) {
7531 err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7532 break;
7533 }
7534
7535 if (_driverKitMatchingAssertionCount != 0) {
7536 err = kPMCPUAssertion;
7537 break;
7538 }
7539
7540 // Check for any dexts currently being added to the PM tree. Sleeping while
7541 // this is in flight can cause IOServicePH to timeout.
7542 if (!IOServicePH::checkPMReady()) {
7543 #if !defined(XNU_TARGET_OS_OSX)
7544 // 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
7545 // in dark wake for long periods of time, which causes issues as apps were
7546 // already informed of sleep during the f->9 transition. As a temporary
7547 // measure, always full wake if we hit this specific condition.
7548 pmPowerStateQueue->submitPowerEvent(
7549 kPowerEventPolicyStimulus,
7550 (void *) kStimulusDarkWakeActivityTickle);
7551 #endif
7552 err = kPMDKNotReady;
7553 break;
7554 }
7555
7556 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7557 kIOPMDriverAssertionLevelOn) {
7558 err = kPMCPUAssertion; // 5. CPU assertion
7559 break;
7560 }
7561
7562 if (pciCantSleepValid) {
7563 if (pciCantSleepFlag) {
7564 err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7565 }
7566 break;
7567 } else if (sleepSupportedPEFunction &&
7568 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7569 IOReturn ret;
7570 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7571 ret = getPlatform()->callPlatformFunction(
7572 sleepSupportedPEFunction.get(), false,
7573 NULL, NULL, NULL, NULL);
7574 pciCantSleepValid = true;
7575 pciCantSleepFlag = false;
7576 if ((platformSleepSupport & kPCICantSleep) ||
7577 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7578 err = 6; // 6. PCI card does not support PM
7579 pciCantSleepFlag = true;
7580 break;
7581 }
7582 }
7583 }while (false);
7584
7585 if (err) {
7586 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7587 return false;
7588 }
7589 return true;
7590 }
7591
7592 bool
7593 IOPMrootDomain::checkSystemSleepEnabled( void )
7594 {
7595 return checkSystemSleepAllowed(0, 0);
7596 }
7597
7598 bool
7599 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7600 {
7601 ASSERT_GATED();
7602 return checkSystemSleepAllowed(1, sleepReason);
7603 }
7604
7605 //******************************************************************************
7606 // checkSystemCanSustainFullWake
7607 //******************************************************************************
7608
7609 bool
7610 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7611 {
7612 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7613 // Low battery wake, or received a low battery notification
7614 // while system is awake. This condition will persist until
7615 // the following wake.
7616 return false;
7617 }
7618
7619 if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7620 // Graphics state is unknown and external display might not be probed.
7621 // Do not incorporate state that requires graphics to be in max power
7622 // such as desktopMode or clamshellDisabled.
7623
7624 if (!acAdaptorConnected) {
7625 DLOG("full wake check: no AC\n");
7626 return false;
7627 }
7628 }
7629 return true;
7630 }
7631
7632 //******************************************************************************
7633 // checkSystemCanAbortIdleSleep
7634 //******************************************************************************
7635
7636 bool
7637 IOPMrootDomain::checkSystemCanAbortIdleSleep( void )
7638 {
7639 bool abortableSleepType = ((lastSleepReason == kIOPMSleepReasonIdle)
7640 || (lastSleepReason == 0));
7641 return idleSleepRevertible && abortableSleepType;
7642 }
7643
7644 //******************************************************************************
7645 // attemptIdleSleepAbort
7646 //******************************************************************************
7647
7648 bool
7649 IOPMrootDomain::attemptIdleSleepAbort( void )
7650 {
7651 if (!gIOPMWorkLoop->inGate()) {
7652 bool ret = gIOPMWorkLoop->runAction(
7653 OSMemberFunctionCast(IOWorkLoop::Action, this,
7654 &IOPMrootDomain::attemptIdleSleepAbort),
7655 this);
7656 return ret;
7657 }
7658
7659 bool canAbort = checkSystemCanAbortIdleSleep();
7660 if (canAbort) {
7661 cancelIdlePowerDownSync();
7662 } else if (lastSleepReason == kIOPMSleepReasonIdle) {
7663 scheduleImmediateDebugWake();
7664 }
7665
7666 return canAbort;
7667 }
7668
7669 //******************************************************************************
7670 // setIdleSleepRevertible
7671 //******************************************************************************
7672
7673 void
7674 IOPMrootDomain::setIdleSleepRevertible( bool revertible )
7675 {
7676 idleSleepRevertible = revertible;
7677 }
7678
7679 //******************************************************************************
7680 // mustHibernate
7681 //******************************************************************************
7682
7683 #if HIBERNATION
7684
7685 bool
7686 IOPMrootDomain::mustHibernate( void )
7687 {
7688 return lowBatteryCondition || thermalWarningState;
7689 }
7690
7691 #endif /* HIBERNATION */
7692
7693 //******************************************************************************
7694 // AOT
7695 //******************************************************************************
7696
7697 // Tables for accumulated days in year by month, latter used for leap years
7698
7699 static const unsigned int daysbymonth[] =
7700 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7701
7702 static const unsigned int lydaysbymonth[] =
7703 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7704
7705 static int __unused
7706 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7707 {
7708 const unsigned int * dbm = daysbymonth;
7709 clock_sec_t n, x, y, z;
7710
7711 // Calculate seconds, minutes and hours
7712
7713 n = secs % (24 * 3600);
7714 dt->second = n % 60;
7715 n /= 60;
7716 dt->minute = n % 60;
7717 dt->hour = (typeof(dt->hour))(n / 60);
7718
7719 // Calculate day of week
7720
7721 n = secs / (24 * 3600);
7722 // dt->dayWeek = (n + 4) % 7;
7723
7724 // Calculate year
7725 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7726 // to days since 1/1/1968 to start on 4 year cycle, beginning
7727 // on a leap year.
7728
7729 n += (366 + 365);
7730
7731 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7732 // Valid before 2100, since 2100 is not a leap year.
7733
7734 x = n / 1461; // number of 4 year cycles
7735 y = n % 1461; // days into current 4 year cycle
7736 z = 1968 + (4 * x);
7737
7738 // Add in years in the current 4 year cycle
7739
7740 if (y >= 366) {
7741 y -= 366; // days after the leap year
7742 n = y % 365; // days into the current year
7743 z += (1 + y / 365); // years after the past 4-yr cycle
7744 } else {
7745 n = y;
7746 dbm = lydaysbymonth;
7747 }
7748 if (z > 2099) {
7749 return 0;
7750 }
7751
7752 dt->year = (typeof(dt->year))z;
7753
7754 // Adjust remaining days value to start at 1
7755
7756 n += 1;
7757
7758 // Calculate month
7759
7760 for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7761 continue;
7762 }
7763 dt->month = (typeof(dt->month))x;
7764
7765 // Calculate day of month
7766
7767 dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7768
7769 return 1;
7770 }
7771
7772 static clock_sec_t
7773 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7774 {
7775 const unsigned int * dbm = daysbymonth;
7776 long y, secs, days;
7777
7778 if (dt->year < 1970 || dt->month > 12) {
7779 return 0;
7780 }
7781
7782 // Seconds elapsed in the current day
7783
7784 secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7785
7786 // Number of days from 1/1/70 to beginning of current year
7787 // Account for extra day every 4 years starting at 1973
7788
7789 y = dt->year - 1970;
7790 days = (y * 365) + ((y + 1) / 4);
7791
7792 // Change table if current year is a leap year
7793
7794 if ((dt->year % 4) == 0) {
7795 dbm = lydaysbymonth;
7796 }
7797
7798 // Add in days elapsed in the current year
7799
7800 days += (dt->day - 1) + dbm[dt->month - 1];
7801
7802 // Add accumulated days to accumulated seconds
7803
7804 secs += 24 * 3600 * days;
7805
7806 return secs;
7807 }
7808
7809 unsigned long
7810 IOPMrootDomain::getRUN_STATE(void)
7811 {
7812 return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
7813 }
7814
7815 bool
7816 IOPMrootDomain::isAOTMode()
7817 {
7818 return _aotNow;
7819 }
7820
7821 IOReturn
7822 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7823 {
7824 clock_sec_t nowsecs, wakesecs;
7825 clock_usec_t nowmicrosecs, wakemicrosecs;
7826 uint64_t nowAbs, wakeAbs;
7827
7828 if (!_aotMode) {
7829 return kIOReturnNotReady;
7830 }
7831
7832 clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
7833 wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
7834 if (wakeAbs < nowAbs) {
7835 printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
7836 wakeAbs = nowAbs;
7837 }
7838 wakeAbs -= nowAbs;
7839 absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7840
7841 wakesecs += nowsecs;
7842 wakemicrosecs += nowmicrosecs;
7843 if (wakemicrosecs >= USEC_PER_SEC) {
7844 wakesecs++;
7845 wakemicrosecs -= USEC_PER_SEC;
7846 }
7847 if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7848 wakesecs++;
7849 }
7850
7851 IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7852
7853 if (_aotWakeTimeContinuous != wakeContinuousTime) {
7854 _aotWakeTimeContinuous = wakeContinuousTime;
7855 IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7856 }
7857 _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7858 _aotWakeTimeUTC = wakesecs;
7859
7860 return kIOReturnSuccess;
7861 }
7862
7863 // assumes WAKEEVENT_LOCK
7864 bool
7865 IOPMrootDomain::aotShouldExit(bool software)
7866 {
7867 bool exitNow = false;
7868 const char * reason = "";
7869
7870 if (!_aotNow) {
7871 return false;
7872 }
7873
7874 if (software) {
7875 exitNow = true;
7876 _aotMetrics->softwareRequestCount++;
7877 reason = "software request";
7878 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7879 exitNow = true;
7880 reason = gWakeReasonString;
7881 } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7882 clock_sec_t sec;
7883 clock_usec_t usec;
7884 clock_get_calendar_microtime(&sec, &usec);
7885 if (_calendarWakeAlarmUTC <= sec) {
7886 exitNow = true;
7887 _aotMetrics->rtcAlarmsCount++;
7888 reason = "user alarm";
7889 }
7890 }
7891 if (exitNow) {
7892 _aotPendingFlags |= kIOPMWakeEventAOTExit;
7893 IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7894 reason,
7895 _aotMetrics->sleepCount,
7896 _aotMetrics->possibleCount,
7897 _aotMetrics->confirmedPossibleCount,
7898 _aotMetrics->rejectedPossibleCount,
7899 _aotMetrics->expiredPossibleCount,
7900 _aotMetrics->noTimeSetCount,
7901 _aotMetrics->rtcAlarmsCount);
7902 }
7903 return exitNow;
7904 }
7905
7906 void
7907 IOPMrootDomain::aotExit(bool cps)
7908 {
7909 uint32_t savedMessageMask;
7910
7911 ASSERT_GATED();
7912 _aotNow = false;
7913 _aotReadyToFullWake = false;
7914 if (_aotTimerScheduled) {
7915 _aotTimerES->cancelTimeout();
7916 _aotTimerScheduled = false;
7917 }
7918 updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
7919
7920 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7921 _aotLastWakeTime = 0;
7922 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7923 WAKEEVENT_LOCK();
7924 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7925 gWakeReasonString,
7926 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7927 WAKEEVENT_UNLOCK();
7928 }
7929
7930 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7931
7932 // Preserve the message mask since a system wake transition
7933 // may have already started and initialized the mask.
7934 savedMessageMask = _systemMessageClientMask;
7935 _systemMessageClientMask = kSystemMessageClientLegacyApp;
7936 tellClients(kIOMessageSystemWillPowerOn);
7937 _systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
7938
7939 if (cps) {
7940 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7941 }
7942 }
7943
7944 void
7945 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7946 {
7947 bool exitNow;
7948
7949 IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7950
7951 WAKEEVENT_LOCK();
7952 exitNow = aotShouldExit(false);
7953 if (timer != NULL) {
7954 _aotTimerScheduled = false;
7955 }
7956 WAKEEVENT_UNLOCK();
7957 if (exitNow) {
7958 aotExit(true);
7959 } else {
7960 #if 0
7961 if (_aotLingerTime) {
7962 uint64_t deadline;
7963 IOLog("aot linger before sleep\n");
7964 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7965 clock_delay_until(deadline);
7966 }
7967 #endif
7968 privateSleepSystem(kIOPMSleepReasonSoftware);
7969 }
7970 }
7971
7972 //******************************************************************************
7973 // adjustPowerState
7974 //
7975 // Conditions that affect our wake/sleep decision has changed.
7976 // If conditions dictate that the system must remain awake, clamp power
7977 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7978 // is TRUE, then remove the power clamp and allow the power state to drop
7979 // to SLEEP_STATE.
7980 //******************************************************************************
7981
7982 void
7983 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7984 {
7985 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7986 getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7987
7988 ASSERT_GATED();
7989
7990 if (_aotNow) {
7991 bool exitNow;
7992
7993 if (AOT_STATE != getPowerState()) {
7994 return;
7995 }
7996 WAKEEVENT_LOCK();
7997 exitNow = aotShouldExit(false);
7998 if (!exitNow
7999 && !_aotTimerScheduled
8000 && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
8001 _aotTimerScheduled = true;
8002 if (_aotLingerTime) {
8003 _aotTimerES->setTimeout(_aotLingerTime);
8004 } else {
8005 _aotTimerES->setTimeout(800, kMillisecondScale);
8006 }
8007 }
8008 WAKEEVENT_UNLOCK();
8009 if (exitNow) {
8010 aotExit(true);
8011 } else {
8012 _aotReadyToFullWake = true;
8013 if (!_aotTimerScheduled) {
8014 if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
8015 // Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
8016 // Doing so will result in the sleep being cancelled anyway,
8017 // but this check avoids unnecessary thrashing in the power state engine.
8018 return;
8019 }
8020 privateSleepSystem(kIOPMSleepReasonSoftware);
8021 }
8022 }
8023 return;
8024 }
8025
8026 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
8027 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
8028 } else if (sleepASAP) {
8029 changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
8030 }
8031 }
8032
8033 void
8034 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
8035 {
8036 if (powerOn) {
8037 if (!checkSystemCanSustainFullWake()) {
8038 DLOG("System cannot sustain full wake\n");
8039 return;
8040 }
8041
8042 // Force wrangler to max power state. If system is in dark wake
8043 // this alone won't raise the wrangler's power state.
8044 if (wrangler) {
8045 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
8046 }
8047
8048 // System in dark wake, always requesting full wake should
8049 // not have any bad side-effects, even if the request fails.
8050
8051 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8052 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
8053 requestFullWake( kFullWakeReasonDisplayOn );
8054 }
8055 } else {
8056 // Relenquish desire to power up display.
8057 // Must first transition to state 1 since wrangler doesn't
8058 // power off the displays at state 0. At state 0 the root
8059 // domain is removed from the wrangler's power client list.
8060 if (wrangler) {
8061 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
8062 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
8063 }
8064 }
8065 }
8066
8067 TUNABLE(bool, test_sleep_in_vm, "test_sleep_in_vm", false);
8068
8069 //******************************************************************************
8070 // dispatchPowerEvent
8071 //
8072 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
8073 //******************************************************************************
8074
8075 void
8076 IOPMrootDomain::dispatchPowerEvent(
8077 uint32_t event, void * arg0, uint64_t arg1 )
8078 {
8079 ASSERT_GATED();
8080
8081 switch (event) {
8082 case kPowerEventFeatureChanged:
8083 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8084 messageClients(kIOPMMessageFeatureChange, this);
8085 break;
8086
8087 case kPowerEventReceivedPowerNotification:
8088 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8089 handlePowerNotification((UInt32)(uintptr_t) arg0 );
8090 break;
8091
8092 case kPowerEventSystemBootCompleted:
8093 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8094 if (systemBooting) {
8095 systemBooting = false;
8096
8097 if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
8098 DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
8099 if (test_sleep_in_vm && gSleepDisabledFlag) {
8100 DLOG("Clearing gSleepDisabledFlag due to test_sleep_in_vm boot-arg\n");
8101 gSleepDisabledFlag = 0;
8102 }
8103 }
8104
8105 if (lowBatteryCondition || thermalEmergencyState) {
8106 if (lowBatteryCondition) {
8107 privateSleepSystem(kIOPMSleepReasonLowPower);
8108 } else {
8109 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8110 }
8111 // The rest is unnecessary since the system is expected
8112 // to sleep immediately. The following wake will update
8113 // everything.
8114 break;
8115 }
8116
8117 sleepWakeDebugMemAlloc();
8118 saveFailureData2File();
8119
8120 // If lid is closed, re-send lid closed notification
8121 // now that booting is complete.
8122 if (clamshellClosed) {
8123 handlePowerNotification(kLocalEvalClamshellCommand);
8124 }
8125 evaluatePolicy( kStimulusAllowSystemSleepChanged );
8126 }
8127 break;
8128
8129 case kPowerEventSystemShutdown:
8130 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8131 if (kOSBooleanTrue == (OSBoolean *) arg0) {
8132 /* We set systemShutdown = true during shutdown
8133 * to prevent sleep at unexpected times while loginwindow is trying
8134 * to shutdown apps and while the OS is trying to transition to
8135 * complete power of.
8136 *
8137 * Set to true during shutdown, as soon as loginwindow shows
8138 * the "shutdown countdown dialog", through individual app
8139 * termination, and through black screen kernel shutdown.
8140 */
8141 systemShutdown = true;
8142 } else {
8143 /*
8144 * A shutdown was initiated, but then the shutdown
8145 * was cancelled, clearing systemShutdown to false here.
8146 */
8147 systemShutdown = false;
8148 }
8149 break;
8150
8151 case kPowerEventUserDisabledSleep:
8152 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8153 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8154 break;
8155
8156 case kPowerEventRegisterSystemCapabilityClient:
8157 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8158
8159 // reset() handles the arg0 == nullptr case for us
8160 systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8161 /* intentional fall-through */
8162 [[clang::fallthrough]];
8163
8164 case kPowerEventRegisterKernelCapabilityClient:
8165 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8166 if (!_joinedCapabilityClients) {
8167 _joinedCapabilityClients = OSSet::withCapacity(8);
8168 }
8169 if (arg0) {
8170 OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8171 if (_joinedCapabilityClients) {
8172 _joinedCapabilityClients->setObject(notify.get());
8173 synchronizePowerTree( kIOPMSyncNoChildNotify );
8174 }
8175 }
8176 break;
8177
8178 case kPowerEventPolicyStimulus:
8179 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8180 if (arg0) {
8181 int stimulus = (int)(uintptr_t) arg0;
8182 evaluatePolicy(stimulus, (uint32_t) arg1);
8183 }
8184 break;
8185
8186 case kPowerEventAssertionCreate:
8187 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8188 if (pmAssertions) {
8189 pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8190 }
8191 break;
8192
8193
8194 case kPowerEventAssertionRelease:
8195 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8196 if (pmAssertions) {
8197 pmAssertions->handleReleaseAssertion(arg1);
8198 }
8199 break;
8200
8201 case kPowerEventAssertionSetLevel:
8202 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8203 if (pmAssertions) {
8204 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8205 }
8206 break;
8207
8208 case kPowerEventQueueSleepWakeUUID:
8209 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8210 handleQueueSleepWakeUUID((OSObject *)arg0);
8211 break;
8212 case kPowerEventPublishSleepWakeUUID:
8213 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8214 handlePublishSleepWakeUUID((bool)arg0);
8215 break;
8216
8217 case kPowerEventSetDisplayPowerOn:
8218 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8219 if (arg1 != 0) {
8220 displayPowerOnRequested = true;
8221 } else {
8222 displayPowerOnRequested = false;
8223 }
8224 handleSetDisplayPowerOn(displayPowerOnRequested);
8225 break;
8226
8227 case kPowerEventPublishWakeType:
8228 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8229
8230 // Don't replace wake type property if already set
8231 if ((arg0 == gIOPMWakeTypeUserKey) ||
8232 !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8233 const char * wakeType = NULL;
8234
8235 if (arg0 == gIOPMWakeTypeUserKey) {
8236 requestUserActive(this, "WakeTypeUser");
8237 wakeType = kIOPMRootDomainWakeTypeUser;
8238 } else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8239 if (!(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
8240 requestUserActive(this, "WakeTypeAlarm");
8241 }
8242 wakeType = kIOPMRootDomainWakeTypeAlarm;
8243 } else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8244 darkWakeSleepService = true;
8245 wakeType = kIOPMRootDomainWakeTypeSleepService;
8246 } else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8247 wakeType = kIOPMRootDomainWakeTypeMaintenance;
8248 }
8249
8250 if (wakeType) {
8251 setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8252 }
8253 }
8254 break;
8255
8256 case kPowerEventAOTEvaluate:
8257 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8258 if (_aotReadyToFullWake) {
8259 aotEvaluate(NULL);
8260 }
8261 break;
8262 }
8263 }
8264
8265 //******************************************************************************
8266 // systemPowerEventOccurred
8267 //
8268 // The power controller is notifying us of a hardware-related power management
8269 // event that we must handle.
8270 //
8271 // systemPowerEventOccurred covers the same functionality that
8272 // receivePowerNotification does; it simply provides a richer API for conveying
8273 // more information.
8274 //******************************************************************************
8275
8276 IOReturn
8277 IOPMrootDomain::systemPowerEventOccurred(
8278 const OSSymbol *event,
8279 uint32_t intValue)
8280 {
8281 IOReturn attempt = kIOReturnSuccess;
8282 OSSharedPtr<OSNumber> newNumber;
8283
8284 if (!event) {
8285 return kIOReturnBadArgument;
8286 }
8287
8288 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8289 if (!newNumber) {
8290 return kIOReturnInternalError;
8291 }
8292
8293 attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8294
8295 return attempt;
8296 }
8297
8298 void
8299 IOPMrootDomain::setThermalState(OSObject *value)
8300 {
8301 OSNumber * num;
8302
8303 if (gIOPMWorkLoop->inGate() == false) {
8304 gIOPMWorkLoop->runAction(
8305 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8306 (OSObject *)this,
8307 (void *)value);
8308
8309 return;
8310 }
8311 if (value && (num = OSDynamicCast(OSNumber, value))) {
8312 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8313 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8314 }
8315 }
8316
8317 IOReturn
8318 IOPMrootDomain::systemPowerEventOccurred(
8319 const OSSymbol *event,
8320 OSObject *value)
8321 {
8322 OSSharedPtr<OSDictionary> thermalsDict;
8323 bool shouldUpdate = true;
8324
8325 if (!event || !value) {
8326 return kIOReturnBadArgument;
8327 }
8328
8329 // LOCK
8330 // We reuse featuresDict Lock because it already exists and guards
8331 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
8332 // of stepping on that lock.
8333 if (featuresDictLock) {
8334 IOLockLock(featuresDictLock);
8335 }
8336
8337 OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8338 OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8339
8340 if (origThermalsDict) {
8341 thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8342 } else {
8343 thermalsDict = OSDictionary::withCapacity(1);
8344 }
8345
8346 if (!thermalsDict) {
8347 shouldUpdate = false;
8348 goto exit;
8349 }
8350
8351 thermalsDict->setObject(event, value);
8352
8353 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8354
8355 exit:
8356 // UNLOCK
8357 if (featuresDictLock) {
8358 IOLockUnlock(featuresDictLock);
8359 }
8360
8361 if (shouldUpdate) {
8362 if (event &&
8363 event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8364 setThermalState(value);
8365 }
8366 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8367 }
8368
8369 return kIOReturnSuccess;
8370 }
8371
8372 //******************************************************************************
8373 // receivePowerNotification
8374 //
8375 // The power controller is notifying us of a hardware-related power management
8376 // event that we must handle. This may be a result of an 'environment' interrupt
8377 // from the power mgt micro.
8378 //******************************************************************************
8379
8380 IOReturn
8381 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8382 {
8383 if (msg & kIOPMPowerButton) {
8384 uint32_t currentPhase = pmTracer->getTracePhase();
8385 if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8386 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8387 swd_flags |= SWD_PWR_BTN_STACKSHOT;
8388 thread_call_enter(powerButtonDown);
8389 } else {
8390 DEBUG_LOG("power button pressed when system is up\n");
8391 }
8392 } else if (msg & kIOPMPowerButtonUp) {
8393 if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8394 swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8395 thread_call_enter(powerButtonUp);
8396 }
8397 } else {
8398 pmPowerStateQueue->submitPowerEvent(
8399 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8400 }
8401 return kIOReturnSuccess;
8402 }
8403
8404 void
8405 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8406 {
8407 bool eval_clamshell = false;
8408 bool eval_clamshell_alarm = false;
8409
8410 ASSERT_GATED();
8411
8412 /*
8413 * Local (IOPMrootDomain only) eval clamshell command
8414 */
8415 if (msg & kLocalEvalClamshellCommand) {
8416 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8417 eval_clamshell_alarm = true;
8418
8419 // reset isRTCAlarmWake. This evaluation should happen only once
8420 // on RTC/Alarm wake. Any clamshell events after wake should follow
8421 // the regular evaluation
8422 isRTCAlarmWake = false;
8423 } else {
8424 eval_clamshell = true;
8425 }
8426 }
8427
8428 /*
8429 * Overtemp
8430 */
8431 if (msg & kIOPMOverTemp) {
8432 DLOG("Thermal overtemp message received!\n");
8433 thermalEmergencyState = true;
8434 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8435 }
8436
8437 /*
8438 * Forward DW thermal notification to client, if system is not going to sleep
8439 */
8440 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8441 DLOG("DarkWake thermal limits message received!\n");
8442 messageClients(kIOPMMessageDarkWakeThermalEmergency);
8443 }
8444
8445 /*
8446 * Sleep Now!
8447 */
8448 if (msg & kIOPMSleepNow) {
8449 privateSleepSystem(kIOPMSleepReasonSoftware);
8450 }
8451
8452 /*
8453 * Power Emergency
8454 */
8455 if (msg & kIOPMPowerEmergency) {
8456 DLOG("Received kIOPMPowerEmergency");
8457 #if HIBERNATION && defined(__arm64__)
8458 if (!ml_is_secure_hib_supported()) {
8459 // Wait for the next low battery notification if the system state is
8460 // in transition.
8461 if ((_systemTransitionType == kSystemTransitionNone) &&
8462 CAP_CURRENT(kIOPMSystemCapabilityCPU) &&
8463 !systemBooting && !systemShutdown && !gWillShutdown) {
8464 // Setting lowBatteryCondition will prevent system sleep
8465 lowBatteryCondition = true;
8466
8467 // Notify userspace to initiate system shutdown
8468 messageClients(kIOPMMessageRequestSystemShutdown);
8469 }
8470 } else {
8471 lowBatteryCondition = true;
8472 privateSleepSystem(kIOPMSleepReasonLowPower);
8473 }
8474 #else /* HIBERNATION && defined(__arm64__) */
8475 lowBatteryCondition = true;
8476 privateSleepSystem(kIOPMSleepReasonLowPower);
8477 #endif /* HIBERNATION && defined(__arm64__) */
8478 }
8479
8480 /*
8481 * Clamshell OPEN
8482 */
8483 if (msg & kIOPMClamshellOpened) {
8484 DLOG("Clamshell opened\n");
8485 // Received clamshel open message from clamshell controlling driver
8486 // Update our internal state and tell general interest clients
8487 clamshellClosed = false;
8488 clamshellExists = true;
8489
8490 // Don't issue a hid tickle when lid is open and polled on wake
8491 if (msg & kIOPMSetValue) {
8492 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8493 reportUserInput();
8494 }
8495
8496 // Tell PMCPU
8497 informCPUStateChange(kInformLid, 0);
8498
8499 // Tell general interest clients
8500 sendClientClamshellNotification();
8501
8502 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
8503 || (lastSleepReason == kIOPMSleepReasonIdle)
8504 || (lastSleepReason == kIOPMSleepReasonMaintenance));
8505 if (aborting) {
8506 userActivityCount++;
8507 }
8508 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8509 }
8510
8511 /*
8512 * Clamshell CLOSED
8513 * Send the clamshell interest notification since the lid is closing.
8514 */
8515 if (msg & kIOPMClamshellClosed) {
8516 if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8517 clamshellClosed && clamshellExists) {
8518 DLOG("Ignoring redundant Clamshell close event\n");
8519 } else {
8520 DLOG("Clamshell closed\n");
8521 // Received clamshel open message from clamshell controlling driver
8522 // Update our internal state and tell general interest clients
8523 clamshellClosed = true;
8524 clamshellExists = true;
8525
8526 // Ignore all following clamshell close events until the clamshell
8527 // is opened or the system sleeps. When a clamshell close triggers
8528 // a system wake, the lid driver may send us two clamshell close
8529 // events, one for the clamshell close event itself, and a second
8530 // close event when the driver polls the lid state on wake.
8531 clamshellIgnoreClose = true;
8532
8533 // Tell PMCPU
8534 informCPUStateChange(kInformLid, 1);
8535
8536 // Tell general interest clients
8537 sendClientClamshellNotification();
8538
8539 // And set eval_clamshell = so we can attempt
8540 eval_clamshell = true;
8541 }
8542 }
8543
8544 /*
8545 * Set Desktop mode (sent from graphics)
8546 *
8547 * -> reevaluate lid state
8548 */
8549 if (msg & kIOPMSetDesktopMode) {
8550 desktopMode = (0 != (msg & kIOPMSetValue));
8551 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8552 DLOG("Desktop mode %d\n", desktopMode);
8553
8554 sendClientClamshellNotification();
8555
8556 // Re-evaluate the lid state
8557 eval_clamshell = true;
8558 }
8559
8560 /*
8561 * AC Adaptor connected
8562 *
8563 * -> reevaluate lid state
8564 */
8565 if (msg & kIOPMSetACAdaptorConnected) {
8566 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8567 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8568
8569 // Tell CPU PM
8570 informCPUStateChange(kInformAC, !acAdaptorConnected);
8571
8572 // Tell BSD if AC is connected
8573 // 0 == external power source; 1 == on battery
8574 post_sys_powersource(acAdaptorConnected ? 0:1);
8575
8576 sendClientClamshellNotification();
8577
8578 IOUserServer::powerSourceChanged(acAdaptorConnected);
8579
8580 // Re-evaluate the lid state
8581 eval_clamshell = true;
8582
8583 // Lack of AC may have latched a display wrangler tickle.
8584 // This mirrors the hardware's USB wake event latch, where a latched
8585 // USB wake event followed by an AC attach will trigger a full wake.
8586 latchDisplayWranglerTickle( false );
8587
8588 #if HIBERNATION
8589 // AC presence will reset the standy timer delay adjustment.
8590 _standbyTimerResetSeconds = 0;
8591 #endif
8592 if (!userIsActive) {
8593 // Reset userActivityTime when power supply is changed(rdr 13789330)
8594 clock_get_uptime(&userActivityTime);
8595 }
8596 }
8597
8598 /*
8599 * Enable Clamshell (external display disappear)
8600 *
8601 * -> reevaluate lid state
8602 */
8603 if (msg & kIOPMEnableClamshell) {
8604 DLOG("Clamshell enabled\n");
8605
8606 // Re-evaluate the lid state
8607 // System should sleep on external display disappearance
8608 // in lid closed operation.
8609 if (true == clamshellDisabled) {
8610 eval_clamshell = true;
8611
8612 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8613 // Also clear kClamshellSleepDisableInternal when graphics enables
8614 // the clamshell during a full wake. When graphics is behaving as
8615 // expected, this will allow clamshell close to be honored earlier
8616 // rather than waiting for the delayed evaluation.
8617 if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8618 (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8619 CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8620 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8621
8622 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8623 // when timer expires which is harmless but useless.
8624 thread_call_cancel(fullWakeThreadCall);
8625 }
8626 #endif
8627 }
8628
8629 clamshellDisabled = false;
8630 sendClientClamshellNotification();
8631 }
8632
8633 /*
8634 * Disable Clamshell (external display appeared)
8635 * We don't bother re-evaluating clamshell state. If the system is awake,
8636 * the lid is probably open.
8637 */
8638 if (msg & kIOPMDisableClamshell) {
8639 DLOG("Clamshell disabled\n");
8640 clamshellDisabled = true;
8641 sendClientClamshellNotification();
8642 }
8643
8644 /*
8645 * Evaluate clamshell and SLEEP if appropriate
8646 */
8647 if (eval_clamshell_alarm && clamshellClosed) {
8648 if (shouldSleepOnRTCAlarmWake()) {
8649 privateSleepSystem(kIOPMSleepReasonClamshell);
8650 }
8651 } else if (eval_clamshell && clamshellClosed) {
8652 if (shouldSleepOnClamshellClosed()) {
8653 privateSleepSystem(kIOPMSleepReasonClamshell);
8654 } else {
8655 evaluatePolicy( kStimulusDarkWakeEvaluate );
8656 }
8657 }
8658
8659 if (msg & kIOPMProModeEngaged) {
8660 int newState = 1;
8661 DLOG("ProModeEngaged\n");
8662 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8663 }
8664
8665 if (msg & kIOPMProModeDisengaged) {
8666 int newState = 0;
8667 DLOG("ProModeDisengaged\n");
8668 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8669 }
8670 }
8671
8672 //******************************************************************************
8673 // evaluatePolicy
8674 //
8675 // Evaluate root-domain policy in response to external changes.
8676 //******************************************************************************
8677
8678 void
8679 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8680 {
8681 union {
8682 struct {
8683 int idleSleepEnabled : 1;
8684 int idleSleepDisabled : 1;
8685 int displaySleep : 1;
8686 int sleepDelayChanged : 1;
8687 int evaluateDarkWake : 1;
8688 int adjustPowerState : 1;
8689 int userBecameInactive : 1;
8690 int displaySleepEntry : 1;
8691 } bit;
8692 uint32_t u32;
8693 } flags;
8694
8695
8696 ASSERT_GATED();
8697 flags.u32 = 0;
8698
8699 switch (stimulus) {
8700 case kStimulusDisplayWranglerSleep:
8701 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8702 if (!wranglerPowerOff) {
8703 // wrangler is in sleep state or lower
8704 flags.bit.displaySleep = true;
8705 }
8706 if (!wranglerAsleep) {
8707 // transition from wrangler wake to wrangler sleep
8708 flags.bit.displaySleepEntry = true;
8709 wranglerAsleep = true;
8710 }
8711 break;
8712
8713 case kStimulusDisplayWranglerWake:
8714 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8715 displayIdleForDemandSleep = false;
8716 wranglerPowerOff = false;
8717 wranglerAsleep = false;
8718 break;
8719
8720 case kStimulusEnterUserActiveState:
8721 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8722 if (_preventUserActive) {
8723 DLOG("user active dropped\n");
8724 break;
8725 }
8726 if (!userIsActive) {
8727 userIsActive = true;
8728 userWasActive = true;
8729 clock_get_uptime(&gUserActiveAbsTime);
8730
8731 // Stay awake after dropping demand for display power on
8732 if (kFullWakeReasonDisplayOn == fullWakeReason) {
8733 fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8734 DLOG("User activity while in notification wake\n");
8735 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8736 }
8737
8738 kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8739 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8740 messageClients(kIOPMMessageUserIsActiveChanged);
8741 }
8742 flags.bit.idleSleepDisabled = true;
8743 break;
8744
8745 case kStimulusLeaveUserActiveState:
8746 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8747 if (userIsActive) {
8748 clock_get_uptime(&gUserInactiveAbsTime);
8749 userIsActive = false;
8750 clock_get_uptime(&userBecameInactiveTime);
8751 flags.bit.userBecameInactive = true;
8752
8753 kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8754 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8755 messageClients(kIOPMMessageUserIsActiveChanged);
8756 }
8757 break;
8758
8759 case kStimulusAggressivenessChanged:
8760 {
8761 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8762 unsigned long aggressiveValue;
8763 uint32_t minutesToIdleSleep = 0;
8764 uint32_t minutesToDisplayDim = 0;
8765 uint32_t minutesDelta = 0;
8766
8767 // Fetch latest display and system sleep slider values.
8768 aggressiveValue = 0;
8769 getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8770 minutesToIdleSleep = (uint32_t) aggressiveValue;
8771
8772 aggressiveValue = 0;
8773 getAggressiveness(kPMMinutesToDim, &aggressiveValue);
8774 minutesToDisplayDim = (uint32_t) aggressiveValue;
8775 DLOG("aggressiveness changed: system %u->%u, display %u\n",
8776 sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
8777
8778 DLOG("idle time -> %d ms (ena %d)\n",
8779 idleMilliSeconds, (minutesToIdleSleep != 0));
8780
8781 // How long to wait before sleeping the system once
8782 // the displays turns off is indicated by 'extraSleepDelay'.
8783
8784 if (minutesToIdleSleep > minutesToDisplayDim) {
8785 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8786 } else if (minutesToIdleSleep == minutesToDisplayDim) {
8787 minutesDelta = 1;
8788 }
8789
8790 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8791 idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8792 }
8793
8794 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8795 flags.bit.idleSleepDisabled = true;
8796 idleSleepEnabled = false;
8797 }
8798 #if !defined(XNU_TARGET_OS_OSX)
8799 if (0x7fffffff == minutesToIdleSleep) {
8800 minutesToIdleSleep = idleMilliSeconds / 1000;
8801 }
8802 #endif /* !defined(XNU_TARGET_OS_OSX) */
8803
8804 if (((minutesDelta != extraSleepDelay) ||
8805 (userActivityTime != userActivityTime_prev)) &&
8806 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8807 flags.bit.sleepDelayChanged = true;
8808 }
8809
8810 if (systemDarkWake && !darkWakeToSleepASAP &&
8811 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8812 // Reconsider decision to remain in dark wake
8813 flags.bit.evaluateDarkWake = true;
8814 }
8815
8816 sleepSlider = minutesToIdleSleep;
8817 extraSleepDelay = minutesDelta;
8818 userActivityTime_prev = userActivityTime;
8819 } break;
8820
8821 case kStimulusDemandSystemSleep:
8822 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8823 displayIdleForDemandSleep = true;
8824 if (wrangler && wranglerIdleSettings) {
8825 // Request wrangler idle only when demand sleep is triggered
8826 // from full wake.
8827 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8828 wrangler->setProperties(wranglerIdleSettings.get());
8829 DLOG("Requested wrangler idle\n");
8830 }
8831 }
8832 // arg = sleepReason
8833 changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8834 break;
8835
8836 case kStimulusAllowSystemSleepChanged:
8837 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8838 flags.bit.adjustPowerState = true;
8839 break;
8840
8841 case kStimulusDarkWakeActivityTickle:
8842 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8843 // arg == true implies real and not self generated wrangler tickle.
8844 // Update wake type on PM work loop instead of the tickle thread to
8845 // eliminate the possibility of an early tickle clobbering the wake
8846 // type set by the platform driver.
8847 if (arg == true) {
8848 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8849 }
8850
8851 if (!darkWakeExit) {
8852 if (latchDisplayWranglerTickle(true)) {
8853 DLOG("latched tickle\n");
8854 break;
8855 }
8856
8857 darkWakeExit = true;
8858 DLOG("Requesting full wake due to dark wake activity tickle\n");
8859 requestFullWake( kFullWakeReasonLocalUser );
8860 }
8861 break;
8862
8863 case kStimulusDarkWakeEntry:
8864 case kStimulusDarkWakeReentry:
8865 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8866 // Any system transitions since the last dark wake transition
8867 // will invalid the stimulus.
8868
8869 if (arg == _systemStateGeneration) {
8870 DLOG("dark wake entry\n");
8871 systemDarkWake = true;
8872
8873 // Keep wranglerPowerOff an invariant when wrangler is absent
8874 if (wrangler) {
8875 wranglerPowerOff = true;
8876 }
8877
8878 if (kStimulusDarkWakeEntry == stimulus) {
8879 clock_get_uptime(&userBecameInactiveTime);
8880 flags.bit.evaluateDarkWake = true;
8881 if (activitySinceSleep()) {
8882 DLOG("User activity recorded while going to darkwake\n");
8883 reportUserInput();
8884 }
8885 }
8886
8887 // Always accelerate disk spindown while in dark wake,
8888 // even if system does not support/allow sleep.
8889
8890 cancelIdleSleepTimer();
8891 setQuickSpinDownTimeout();
8892 }
8893 break;
8894
8895 case kStimulusDarkWakeEvaluate:
8896 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8897 if (systemDarkWake) {
8898 flags.bit.evaluateDarkWake = true;
8899 }
8900 break;
8901
8902 case kStimulusNoIdleSleepPreventers:
8903 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8904 flags.bit.adjustPowerState = true;
8905 break;
8906 } /* switch(stimulus) */
8907
8908 if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
8909 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8910 darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
8911 if (darkWakeToSleepASAP ||
8912 (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
8913 uint32_t newSleepReason;
8914
8915 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8916 // System was previously in full wake. Sleep reason from
8917 // full to dark already recorded in fullToDarkReason.
8918
8919 if (lowBatteryCondition) {
8920 newSleepReason = kIOPMSleepReasonLowPower;
8921 } else if (thermalEmergencyState) {
8922 newSleepReason = kIOPMSleepReasonThermalEmergency;
8923 } else {
8924 newSleepReason = fullToDarkReason;
8925 }
8926 } else {
8927 // In dark wake from system sleep.
8928
8929 if (darkWakeSleepService) {
8930 newSleepReason = kIOPMSleepReasonSleepServiceExit;
8931 } else {
8932 newSleepReason = kIOPMSleepReasonMaintenance;
8933 }
8934 }
8935
8936 if (checkSystemCanSleep(newSleepReason)) {
8937 privateSleepSystem(newSleepReason);
8938 }
8939 } else { // non-maintenance (network) dark wake
8940 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8941 // Release power clamp, and wait for children idle.
8942 adjustPowerState(true);
8943 } else {
8944 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8945 }
8946 }
8947 }
8948
8949 if (systemDarkWake) {
8950 // The rest are irrelevant while system is in dark wake.
8951 flags.u32 = 0;
8952 }
8953
8954 if ((flags.bit.displaySleepEntry) &&
8955 (kFullWakeReasonDisplayOn == fullWakeReason)) {
8956 // kIOPMSleepReasonNotificationWakeExit
8957 DLOG("Display sleep while in notification wake\n");
8958 changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8959 }
8960
8961 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8962 bool cancelQuickSpindown = false;
8963
8964 if (flags.bit.sleepDelayChanged) {
8965 // Cancel existing idle sleep timer and quick disk spindown.
8966 // New settings will be applied by the idleSleepEnabled flag
8967 // handler below if idle sleep is enabled.
8968
8969 DLOG("extra sleep timer changed\n");
8970 cancelIdleSleepTimer();
8971 cancelQuickSpindown = true;
8972 } else {
8973 DLOG("user inactive\n");
8974 }
8975
8976 if (!userIsActive && idleSleepEnabled) {
8977 startIdleSleepTimer(getTimeToIdleSleep());
8978 }
8979
8980 if (cancelQuickSpindown) {
8981 restoreUserSpinDownTimeout();
8982 }
8983 }
8984
8985 if (flags.bit.idleSleepEnabled) {
8986 DLOG("idle sleep timer enabled\n");
8987 if (!wrangler) {
8988 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8989 startIdleSleepTimer(getTimeToIdleSleep());
8990 #else
8991 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8992 startIdleSleepTimer( idleMilliSeconds );
8993 #endif
8994 } else {
8995 // Start idle timer if prefs now allow system sleep
8996 // and user is already inactive. Disk spindown is
8997 // accelerated upon timer expiration.
8998
8999 if (!userIsActive) {
9000 startIdleSleepTimer(getTimeToIdleSleep());
9001 }
9002 }
9003 }
9004
9005 if (flags.bit.idleSleepDisabled) {
9006 DLOG("idle sleep timer disabled\n");
9007 cancelIdleSleepTimer();
9008 restoreUserSpinDownTimeout();
9009 adjustPowerState();
9010 }
9011
9012 if (flags.bit.adjustPowerState) {
9013 bool sleepASAP = false;
9014
9015 if (!systemBooting && (0 == idleSleepPreventersCount())) {
9016 if (!wrangler) {
9017 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
9018 if (idleSleepEnabled) {
9019 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
9020 if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
9021 sleepASAP = true;
9022 }
9023 #else
9024 // stay awake for at least idleMilliSeconds
9025 startIdleSleepTimer(idleMilliSeconds);
9026 #endif
9027 }
9028 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
9029 sleepASAP = true;
9030 }
9031 }
9032
9033 adjustPowerState(sleepASAP);
9034 }
9035 }
9036
9037 //******************************************************************************
9038
9039 unsigned int
9040 IOPMrootDomain::idleSleepPreventersCount()
9041 {
9042 if (_aotMode) {
9043 unsigned int count __block;
9044 count = 0;
9045 preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
9046 {
9047 count += (NULL == obj->metaCast("AppleARMBacklight"));
9048 return false;
9049 });
9050 return count;
9051 }
9052
9053 return preventIdleSleepList->getCount();
9054 }
9055
9056
9057 //******************************************************************************
9058 // requestFullWake
9059 //
9060 // Request transition from dark wake to full wake
9061 //******************************************************************************
9062
9063 void
9064 IOPMrootDomain::requestFullWake( FullWakeReason reason )
9065 {
9066 uint32_t options = 0;
9067 IOService * pciRoot = NULL;
9068 bool promotion = false;
9069
9070 // System must be in dark wake and a valid reason for entering full wake
9071 if ((kFullWakeReasonNone == reason) ||
9072 (kFullWakeReasonNone != fullWakeReason) ||
9073 (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
9074 return;
9075 }
9076
9077 // Will clear reason upon exit from full wake
9078 fullWakeReason = reason;
9079
9080 _desiredCapability |= (kIOPMSystemCapabilityGraphics |
9081 kIOPMSystemCapabilityAudio);
9082
9083 if ((kSystemTransitionWake == _systemTransitionType) &&
9084 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
9085 !darkWakePowerClamped) {
9086 // Promote to full wake while waking up to dark wake due to tickle.
9087 // PM will hold off notifying the graphics subsystem about system wake
9088 // as late as possible, so if a HID tickle does arrive, graphics can
9089 // power up from this same wake transition. Otherwise, the latency to
9090 // power up graphics on the following transition can be huge on certain
9091 // systems. However, once any power clamping has taken effect, it is
9092 // too late to promote the current dark wake transition to a full wake.
9093 _pendingCapability |= (kIOPMSystemCapabilityGraphics |
9094 kIOPMSystemCapabilityAudio);
9095
9096 // Tell the PCI parent of audio and graphics drivers to stop
9097 // delaying the child notifications. Same for root domain.
9098 pciRoot = pciHostBridgeDriver.get();
9099 willEnterFullWake();
9100 promotion = true;
9101 }
9102
9103 // Unsafe to cancel once graphics was powered.
9104 // If system woke from dark wake, the return to sleep can
9105 // be cancelled. "awake -> dark -> sleep" transition
9106 // can be cancelled also, during the "dark -> sleep" phase
9107 // *prior* to driver power down.
9108 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
9109 _pendingCapability == 0) {
9110 options |= kIOPMSyncCancelPowerDown;
9111 }
9112
9113 synchronizePowerTree(options, pciRoot);
9114
9115 if (kFullWakeReasonLocalUser == fullWakeReason) {
9116 // IOGraphics doesn't light the display even though graphics is
9117 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
9118 // So, do an explicit activity tickle
9119 if (wrangler) {
9120 wrangler->activityTickle(0, 0);
9121 }
9122 }
9123
9124 // Log a timestamp for the initial full wake request.
9125 // System may not always honor this full wake request.
9126 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9127 AbsoluteTime now;
9128 uint64_t nsec;
9129
9130 clock_get_uptime(&now);
9131 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9132 absolutetime_to_nanoseconds(now, &nsec);
9133 MSG("full wake %s (reason %u) %u ms\n",
9134 promotion ? "promotion" : "request",
9135 fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9136 }
9137 }
9138
9139 //******************************************************************************
9140 // willEnterFullWake
9141 //
9142 // System will enter full wake from sleep, from dark wake, or from dark
9143 // wake promotion. This function aggregate things that are in common to
9144 // all three full wake transitions.
9145 //
9146 // Assumptions: fullWakeReason was updated
9147 //******************************************************************************
9148
9149 void
9150 IOPMrootDomain::willEnterFullWake( void )
9151 {
9152 hibernateRetry = false;
9153 sleepToStandby = false;
9154 standbyNixed = false;
9155 resetTimers = false;
9156 sleepTimerMaintenance = false;
9157
9158 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9159
9160 _systemMessageClientMask = kSystemMessageClientPowerd |
9161 kSystemMessageClientLegacyApp;
9162
9163 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9164 // First time to attain full wake capability since the last wake
9165 _systemMessageClientMask |= kSystemMessageClientKernel;
9166
9167 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9168 setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9169 (kFullWakeReasonLocalUser == fullWakeReason) ?
9170 kOSBooleanTrue : kOSBooleanFalse);
9171 }
9172 #if HIBERNATION
9173 IOHibernateSetWakeCapabilities(_pendingCapability);
9174 #endif
9175
9176 IOService::setAdvisoryTickleEnable( true );
9177 tellClients(kIOMessageSystemWillPowerOn);
9178 preventTransitionToUserActive(false);
9179 }
9180
9181 //******************************************************************************
9182 // fullWakeDelayedWork
9183 //
9184 // System has already entered full wake. Invoked by a delayed thread call.
9185 //******************************************************************************
9186
9187 void
9188 IOPMrootDomain::fullWakeDelayedWork( void )
9189 {
9190 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9191 if (!gIOPMWorkLoop->inGate()) {
9192 gIOPMWorkLoop->runAction(
9193 OSMemberFunctionCast(IOWorkLoop::Action, this,
9194 &IOPMrootDomain::fullWakeDelayedWork), this);
9195 return;
9196 }
9197
9198 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9199 _currentCapability, _pendingCapability, _highestCapability,
9200 clamshellDisabled, clamshellSleepDisableMask);
9201
9202 if (clamshellExists &&
9203 CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9204 !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9205 if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9206 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9207 } else {
9208 // Not the initial full wake after waking from sleep.
9209 // Evaluate the clamshell for rdar://problem/9157444.
9210 receivePowerNotification(kLocalEvalClamshellCommand);
9211 }
9212 }
9213 #endif
9214 }
9215
9216 //******************************************************************************
9217 // evaluateAssertions
9218 //
9219 //******************************************************************************
9220
9221 // Bitmask of all kernel assertions that prevent system idle sleep.
9222 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9223 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9224 (kIOPMDriverAssertionReservedBit7 | \
9225 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9226
9227 void
9228 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9229 {
9230 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9231
9232 messageClients(kIOPMMessageDriverAssertionsChanged);
9233
9234 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9235 if (wrangler) {
9236 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9237
9238 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9239 wrangler->setIgnoreIdleTimer( value );
9240 }
9241 }
9242
9243 if (changedBits & kIOPMDriverAssertionCPUBit) {
9244 if (_aotNow) {
9245 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9246 }
9247 evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9248 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9249 AbsoluteTime now;
9250 clock_usec_t microsecs;
9251 clock_get_uptime(&now);
9252 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9253 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
9254 if (assertOnWakeReport) {
9255 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9256 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9257 }
9258 }
9259 }
9260
9261 if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9262 if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9263 if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9264 DLOG("PreventIdleSleep driver assertion raised\n");
9265 bool ok = updatePreventIdleSleepList(this, true);
9266 if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9267 // Cancel idle sleep if there is one in progress
9268 cancelIdlePowerDown(this);
9269 }
9270 }
9271 } else {
9272 DLOG("PreventIdleSleep driver assertion dropped\n");
9273 updatePreventIdleSleepList(this, false);
9274 }
9275 }
9276 }
9277
9278 // MARK: -
9279 // MARK: Statistics
9280
9281 //******************************************************************************
9282 // pmStats
9283 //
9284 //******************************************************************************
9285
9286 void
9287 IOPMrootDomain::pmStatsRecordEvent(
9288 int eventIndex,
9289 AbsoluteTime timestamp)
9290 {
9291 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9292 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9293 uint64_t delta;
9294 uint64_t nsec;
9295 OSSharedPtr<OSData> publishPMStats;
9296
9297 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9298
9299 absolutetime_to_nanoseconds(timestamp, &nsec);
9300
9301 switch (eventIndex) {
9302 case kIOPMStatsHibernateImageWrite:
9303 if (starting) {
9304 gPMStats.hibWrite.start = nsec;
9305 } else if (stopping) {
9306 gPMStats.hibWrite.stop = nsec;
9307 }
9308
9309 if (stopping) {
9310 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9311 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9312 }
9313 break;
9314 case kIOPMStatsHibernateImageRead:
9315 if (starting) {
9316 gPMStats.hibRead.start = nsec;
9317 } else if (stopping) {
9318 gPMStats.hibRead.stop = nsec;
9319 }
9320
9321 if (stopping) {
9322 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9323 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9324
9325 publishPMStats = OSData::withValue(gPMStats);
9326 setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9327 bzero(&gPMStats, sizeof(gPMStats));
9328 }
9329 break;
9330 }
9331 }
9332
9333 /*
9334 * Appends a record of the application response to
9335 * IOPMrootDomain::pmStatsAppResponses
9336 */
9337 void
9338 IOPMrootDomain::pmStatsRecordApplicationResponse(
9339 const OSSymbol *response,
9340 const char *name,
9341 int messageType,
9342 uint32_t delay_ms,
9343 uint64_t id,
9344 OSObject *object,
9345 IOPMPowerStateIndex powerState,
9346 bool async)
9347 {
9348 OSSharedPtr<OSDictionary> responseDescription;
9349 OSSharedPtr<OSNumber> delayNum;
9350 OSSharedPtr<OSNumber> powerCaps;
9351 OSSharedPtr<OSNumber> pidNum;
9352 OSSharedPtr<OSNumber> msgNum;
9353 OSSharedPtr<const OSSymbol> appname;
9354 OSSharedPtr<const OSSymbol> sleep;
9355 OSSharedPtr<const OSSymbol> wake;
9356 IOPMServiceInterestNotifier *notify = NULL;
9357
9358 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9359 if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9360 notify->ackTimeoutCnt++;
9361 } else {
9362 notify->ackTimeoutCnt = 0;
9363 }
9364 }
9365
9366 if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9367 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9368 return;
9369 }
9370
9371
9372 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9373 kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9374 } else if (notify) {
9375 // User space app or kernel capability client
9376 if (id) {
9377 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9378 } else {
9379 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9380 }
9381 notify->msgType = 0;
9382 }
9383
9384 responseDescription = OSDictionary::withCapacity(5);
9385 if (responseDescription) {
9386 if (response) {
9387 responseDescription->setObject(_statsResponseTypeKey.get(), response);
9388 }
9389
9390 msgNum = OSNumber::withNumber(messageType, 32);
9391 if (msgNum) {
9392 responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9393 }
9394
9395 if (!name && notify && notify->identifier) {
9396 name = notify->identifier->getCStringNoCopy();
9397 }
9398
9399 if (name && (strlen(name) > 0)) {
9400 appname = OSSymbol::withCString(name);
9401 if (appname) {
9402 responseDescription->setObject(_statsNameKey.get(), appname.get());
9403 }
9404 }
9405
9406 if (!id && notify) {
9407 id = notify->uuid0;
9408 }
9409 pidNum = OSNumber::withNumber(id, 64);
9410 if (pidNum) {
9411 responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9412 }
9413
9414 delayNum = OSNumber::withNumber(delay_ms, 32);
9415 if (delayNum) {
9416 responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9417 }
9418
9419 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9420 powerCaps = OSNumber::withNumber(powerState, 32);
9421
9422 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9423 static const char * driverCallTypes[] = {
9424 [kDriverCallInformPreChange] = "powerStateWillChangeTo",
9425 [kDriverCallInformPostChange] = "powerStateDidChangeTo",
9426 [kDriverCallSetPowerState] = "setPowerState"
9427 };
9428
9429 if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9430 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9431 name, id, driverCallTypes[messageType], (uint32_t) powerState,
9432 async ? "async " : "", delay_ms);
9433 }
9434 #endif
9435 } else {
9436 powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9437 }
9438 if (powerCaps) {
9439 responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9440 }
9441
9442 sleep = OSSymbol::withCString("Sleep");
9443 wake = OSSymbol::withCString("Wake");
9444 if (_systemTransitionType == kSystemTransitionSleep) {
9445 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9446 } else if (_systemTransitionType == kSystemTransitionWake) {
9447 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9448 } else if (_systemTransitionType == kSystemTransitionCapability) {
9449 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9450 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9451 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9452 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9453 }
9454 }
9455
9456 IOLockLock(pmStatsLock);
9457 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9458 pmStatsAppResponses->setObject(responseDescription.get());
9459 }
9460 IOLockUnlock(pmStatsLock);
9461 }
9462
9463 return;
9464 }
9465
9466 // MARK: -
9467 // MARK: PMTraceWorker
9468
9469 //******************************************************************************
9470 // TracePoint support
9471 //
9472 //******************************************************************************
9473
9474 #define kIOPMRegisterNVRAMTracePointHandlerKey \
9475 "IOPMRegisterNVRAMTracePointHandler"
9476
9477 IOReturn
9478 IOPMrootDomain::callPlatformFunction(
9479 const OSSymbol * functionName,
9480 bool waitForFunction,
9481 void * param1, void * param2,
9482 void * param3, void * param4 )
9483 {
9484 if (pmTracer && functionName &&
9485 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9486 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9487 uint32_t tracePointPhases, tracePointPCI;
9488 uint64_t statusCode;
9489
9490 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9491 pmTracer->tracePointTarget = (void *) param2;
9492 tracePointPCI = (uint32_t)(uintptr_t) param3;
9493 tracePointPhases = (uint32_t)(uintptr_t) param4;
9494 if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9495 OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9496 if (node) {
9497 OSSharedPtr<OSObject> bootRomFailureProp;
9498 bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9499 OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9500 uint32_t bootFailureCode;
9501 if (data && data->getLength() == sizeof(bootFailureCode)) {
9502 // Failure code from EFI/BootRom is a four byte structure
9503 memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9504 tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9505 }
9506 }
9507 }
9508 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9509 if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9510 MSG("Sleep failure code 0x%08x 0x%08x\n",
9511 tracePointPCI, tracePointPhases);
9512 }
9513 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9514 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9515
9516 return kIOReturnSuccess;
9517 }
9518 #if HIBERNATION
9519 else if (functionName &&
9520 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9521 if (gSleepPolicyHandler) {
9522 return kIOReturnExclusiveAccess;
9523 }
9524 if (!param1) {
9525 return kIOReturnBadArgument;
9526 }
9527 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9528 gSleepPolicyTarget = (void *) param2;
9529 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9530 return kIOReturnSuccess;
9531 }
9532 #endif
9533
9534 return super::callPlatformFunction(
9535 functionName, waitForFunction, param1, param2, param3, param4);
9536 }
9537
9538 void
9539 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9540 uintptr_t param1, uintptr_t param2, uintptr_t param3)
9541 {
9542 uint32_t code = IODBG_POWER(event);
9543 uint64_t regId = id;
9544 if (regId == 0) {
9545 regId = getRegistryEntryID();
9546 }
9547 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9548 }
9549
9550 void
9551 IOPMrootDomain::tracePoint( uint8_t point )
9552 {
9553 if (systemBooting) {
9554 return;
9555 }
9556
9557 if (kIOPMTracePointWakeCapabilityClients == point) {
9558 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9559 }
9560
9561 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9562 pmTracer->tracePoint(point);
9563 }
9564
9565 static void
9566 kext_log_putc(char c)
9567 {
9568 if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9569 return;
9570 }
9571 if (c == '(' || c == '[' || c == ' ') {
9572 c = 0;
9573 gKextNameEnd = true;
9574 }
9575
9576 gKextNameBuf[gKextNamePos++] = c;
9577 }
9578
9579 static int
9580 kext_log(const char *fmt, ...)
9581 {
9582 va_list listp;
9583
9584 va_start(listp, fmt);
9585 _doprnt(fmt, &listp, &kext_log_putc, 16);
9586 va_end(listp);
9587
9588 return 0;
9589 }
9590
9591 static OSPtr<const OSSymbol>
9592 copyKextIdentifierWithAddress(vm_address_t address)
9593 {
9594 OSSharedPtr<const OSSymbol> identifer;
9595
9596 IOLockLock(gHaltLogLock);
9597
9598 gKextNameEnd = false;
9599 gKextNamePos = 0;
9600 gKextNameBuf[0] = 0;
9601
9602 OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9603 gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9604 identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9605
9606 IOLockUnlock(gHaltLogLock);
9607
9608 return identifer;
9609 }
9610
9611 // Caller serialized using PM workloop
9612 const char *
9613 IOPMrootDomain::getNotificationClientName(OSObject *object)
9614 {
9615 IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9616 const char *clientName = "UNKNOWN";
9617
9618 if (!notifier->clientName) {
9619 // Check for user client
9620 if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9621 OSNumber *clientID = NULL;
9622 messageClient(kIOMessageCopyClientID, object, &clientID);
9623 if (clientID) {
9624 OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9625 if (string) {
9626 notifier->clientName = OSSymbol::withString(string.get());
9627 }
9628 clientID->release();
9629 }
9630 } else if (notifier->identifier) {
9631 notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9632 }
9633 }
9634
9635 if (notifier->clientName) {
9636 clientName = notifier->clientName->getCStringNoCopy();
9637 }
9638
9639 return clientName;
9640 }
9641
9642 void
9643 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9644 {
9645 IOPMServiceInterestNotifier *notifier;
9646
9647 if (systemBooting) {
9648 return;
9649 }
9650 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9651 if (!notifier) {
9652 return;
9653 }
9654
9655 if (start) {
9656 pmTracer->traceDetail(notifier->uuid0 >> 32);
9657 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9658 (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9659
9660 // Update notifier state used for response/ack logging
9661 notifier->msgIndex = msgIndex;
9662 notifier->msgAbsTime = timestamp;
9663
9664 if (msgIndex != UINT_MAX) {
9665 DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9666 } else {
9667 DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9668 }
9669
9670 assert(notifierObject == NULL);
9671 notifierThread = current_thread();
9672 notifierObject.reset(notifier, OSRetain);
9673 } else {
9674 uint64_t nsec;
9675 uint32_t delayMS;
9676
9677 SUB_ABSOLUTETIME(×tamp, ¬ifier->msgAbsTime);
9678 absolutetime_to_nanoseconds(timestamp, &nsec);
9679 delayMS = (uint32_t)(nsec / 1000000ULL);
9680 if (delayMS > notifier->maxMsgDelayMS) {
9681 notifier->maxMsgDelayMS = delayMS;
9682 }
9683
9684 assert(notifierObject == notifier);
9685 notifierObject.reset();
9686 notifierThread = NULL;
9687 }
9688 }
9689
9690 void
9691 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9692 {
9693 if (systemBooting) {
9694 return;
9695 }
9696 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9697 if (!notifier) {
9698 return;
9699 }
9700
9701 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9702 (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9703
9704 DLOG("%s[%u] ack from %s took %d ms\n",
9705 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9706 if (delay_ms > notifier->maxAckDelayMS) {
9707 notifier->maxAckDelayMS = delay_ms;
9708 }
9709 }
9710
9711 void
9712 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9713 {
9714 if (systemBooting) {
9715 return;
9716 }
9717 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9718 if (!notifier) {
9719 return;
9720 }
9721
9722 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9723 (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9724
9725 if (ack_time_us == 0) {
9726 // Client work is done and ack will not be forthcoming
9727 DLOG("%s[%u] response from %s took %d ms\n",
9728 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9729 } else {
9730 // Client needs more time and it must ack within ack_time_us
9731 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9732 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9733 }
9734 }
9735
9736 void
9737 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9738 {
9739 if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9740 return;
9741 }
9742 if (systemBooting) {
9743 return;
9744 }
9745 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9746 if (!notifier) {
9747 return;
9748 }
9749
9750 DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9751 }
9752
9753 void
9754 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9755 {
9756 if (!systemBooting) {
9757 uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
9758 pmTracer->traceDetail( detail );
9759 kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
9760 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
9761 }
9762 }
9763
9764 void
9765 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9766 {
9767 size_t reportSize;
9768 void **report = NULL;
9769 uint32_t bktCnt;
9770 uint32_t bktSize;
9771 uint32_t *clientCnt;
9772
9773 ASSERT_GATED();
9774
9775 report = NULL;
9776 if (channel_id == kAssertDelayChID) {
9777 report = &assertOnWakeReport;
9778 bktCnt = kAssertDelayBcktCnt;
9779 bktSize = kAssertDelayBcktSize;
9780 clientCnt = &assertOnWakeClientCnt;
9781 } else if (channel_id == kSleepDelaysChID) {
9782 report = &sleepDelaysReport;
9783 bktCnt = kSleepDelaysBcktCnt;
9784 bktSize = kSleepDelaysBcktSize;
9785 clientCnt = &sleepDelaysClientCnt;
9786 } else {
9787 assert(false);
9788 return;
9789 }
9790
9791 switch (action) {
9792 case kIOReportEnable:
9793
9794 if (*report) {
9795 (*clientCnt)++;
9796 break;
9797 }
9798
9799 reportSize = HISTREPORT_BUFSIZE(bktCnt);
9800 *report = IOMallocZeroData(reportSize);
9801 if (*report == NULL) {
9802 break;
9803 }
9804 HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9805 getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9806
9807 if (channel_id == kAssertDelayChID) {
9808 assertOnWakeSecs = 0;
9809 }
9810
9811 break;
9812
9813 case kIOReportDisable:
9814 if (*clientCnt == 0) {
9815 break;
9816 }
9817 if (*clientCnt == 1) {
9818 IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
9819 *report = NULL;
9820 }
9821 (*clientCnt)--;
9822
9823 if (channel_id == kAssertDelayChID) {
9824 assertOnWakeSecs = -1; // Invalid value to prevent updates
9825 }
9826 break;
9827
9828 case kIOReportGetDimensions:
9829 if (*report) {
9830 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9831 }
9832 break;
9833 }
9834
9835 return;
9836 }
9837
9838 IOReturn
9839 IOPMrootDomain::configureReport(IOReportChannelList *channelList,
9840 IOReportConfigureAction action,
9841 void *result,
9842 void *destination)
9843 {
9844 unsigned cnt;
9845 uint64_t configAction = (uint64_t)action;
9846
9847 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9848 if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
9849 (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
9850 (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
9851 if (action != kIOReportGetDimensions) {
9852 continue;
9853 }
9854 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
9855 } else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
9856 (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
9857 gIOPMWorkLoop->runAction(
9858 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
9859 (OSObject *)this, (void *)channelList->channels[cnt].channel_id,
9860 (void *)configAction, (void *)result);
9861 }
9862 }
9863
9864 return super::configureReport(channelList, action, result, destination);
9865 }
9866
9867 IOReturn
9868 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9869 {
9870 uint32_t size2cpy;
9871 void *data2cpy;
9872 void **report;
9873
9874 ASSERT_GATED();
9875
9876 report = NULL;
9877 if (ch_id == kAssertDelayChID) {
9878 report = &assertOnWakeReport;
9879 } else if (ch_id == kSleepDelaysChID) {
9880 report = &sleepDelaysReport;
9881 } else {
9882 assert(false);
9883 return kIOReturnBadArgument;
9884 }
9885
9886 if (*report == NULL) {
9887 return kIOReturnNotOpen;
9888 }
9889
9890 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9891 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9892 return kIOReturnOverrun;
9893 }
9894
9895 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9896 dest->appendBytes(data2cpy, size2cpy);
9897
9898 return kIOReturnSuccess;
9899 }
9900
9901 IOReturn
9902 IOPMrootDomain::updateReport(IOReportChannelList *channelList,
9903 IOReportUpdateAction action,
9904 void *result,
9905 void *destination)
9906 {
9907 uint32_t size2cpy;
9908 void *data2cpy;
9909 uint8_t buf[SIMPLEREPORT_BUFSIZE];
9910 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9911 unsigned cnt;
9912 uint64_t ch_id;
9913
9914 if (action != kIOReportCopyChannelData) {
9915 goto exit;
9916 }
9917
9918 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9919 ch_id = channelList->channels[cnt].channel_id;
9920
9921 if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
9922 gIOPMWorkLoop->runAction(
9923 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
9924 (OSObject *)this, (void *)ch_id,
9925 (void *)result, (void *)dest);
9926 continue;
9927 } else if ((ch_id == kSleepCntChID) ||
9928 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9929 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9930 } else {
9931 continue;
9932 }
9933
9934 if (ch_id == kSleepCntChID) {
9935 SIMPLEREPORT_SETVALUE(buf, sleepCnt);
9936 } else if (ch_id == kDarkWkCntChID) {
9937 SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
9938 } else if (ch_id == kUserWkCntChID) {
9939 SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
9940 }
9941
9942 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9943 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9944 dest->appendBytes(data2cpy, size2cpy);
9945 }
9946
9947 exit:
9948 return super::updateReport(channelList, action, result, destination);
9949 }
9950
9951
9952 //******************************************************************************
9953 // PMTraceWorker Class
9954 //
9955 //******************************************************************************
9956
9957 #undef super
9958 #define super OSObject
9959 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9960
9961 #define kPMBestGuessPCIDevicesCount 25
9962 #define kPMMaxRTCBitfieldSize 32
9963
9964 OSPtr<PMTraceWorker>
9965 PMTraceWorker::tracer(IOPMrootDomain * owner)
9966 {
9967 OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9968 if (!me || !me->init()) {
9969 return NULL;
9970 }
9971
9972 DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9973
9974 // Note that we cannot instantiate the PCI device -> bit mappings here, since
9975 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
9976 // this dictionary lazily.
9977 me->owner = owner;
9978 me->pciDeviceBitMappings = NULL;
9979 me->pmTraceWorkerLock = IOLockAlloc();
9980 me->tracePhase = kIOPMTracePointSystemUp;
9981 me->traceData32 = 0;
9982 me->loginWindowData = 0;
9983 me->coreDisplayData = 0;
9984 me->coreGraphicsData = 0;
9985 return me;
9986 }
9987
9988 void
9989 PMTraceWorker::RTC_TRACE(void)
9990 {
9991 if (tracePointHandler && tracePointTarget) {
9992 uint32_t wordA;
9993
9994 IOLockLock(pmTraceWorkerLock);
9995 wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9996 (coreGraphicsData << 8) | tracePhase;
9997 IOLockUnlock(pmTraceWorkerLock);
9998
9999 tracePointHandler( tracePointTarget, traceData32, wordA );
10000 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
10001 }
10002 #if DEVELOPMENT || DEBUG
10003 if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
10004 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
10005 IOLock *l = IOLockAlloc();
10006 IOLockLock(l);
10007 IOLockLock(l);
10008 }
10009 #endif /* DEVELOPMENT || DEBUG */
10010 }
10011
10012 int
10013 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
10014 {
10015 OSSharedPtr<const OSSymbol> deviceName;
10016 int index = -1;
10017
10018 IOLockLock(pmTraceWorkerLock);
10019
10020 if (!pciDeviceBitMappings) {
10021 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
10022 if (!pciDeviceBitMappings) {
10023 goto exit;
10024 }
10025 }
10026
10027 // Check for bitmask overflow.
10028 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
10029 goto exit;
10030 }
10031
10032 if ((deviceName = pciDevice->copyName()) &&
10033 (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
10034 pciDeviceBitMappings->setObject(deviceName.get())) {
10035 index = pciDeviceBitMappings->getCount() - 1;
10036 _LOG("PMTrace PCI array: set object %s => %d\n",
10037 deviceName->getCStringNoCopy(), index);
10038 }
10039
10040 if (!addedToRegistry && (index >= 0)) {
10041 addedToRegistry = owner->setProperty("PCITopLevel", this);
10042 }
10043
10044 exit:
10045 IOLockUnlock(pmTraceWorkerLock);
10046 return index;
10047 }
10048
10049 bool
10050 PMTraceWorker::serialize(OSSerialize *s) const
10051 {
10052 bool ok = false;
10053 if (pciDeviceBitMappings) {
10054 IOLockLock(pmTraceWorkerLock);
10055 ok = pciDeviceBitMappings->serialize(s);
10056 IOLockUnlock(pmTraceWorkerLock);
10057 }
10058 return ok;
10059 }
10060
10061 void
10062 PMTraceWorker::tracePoint(uint8_t phase)
10063 {
10064 // clear trace detail when phase begins
10065 if (tracePhase != phase) {
10066 traceData32 = 0;
10067 }
10068
10069 tracePhase = phase;
10070
10071 DLOG("trace point 0x%02x\n", tracePhase);
10072 RTC_TRACE();
10073 }
10074
10075 void
10076 PMTraceWorker::traceDetail(uint32_t detail)
10077 {
10078 if (detail == traceData32) {
10079 return;
10080 }
10081 traceData32 = detail;
10082 RTC_TRACE();
10083 }
10084
10085 void
10086 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
10087 {
10088 switch (component) {
10089 case kIOPMLoginWindowProgress:
10090 loginWindowData = data & kIOPMLoginWindowProgressMask;
10091 break;
10092 case kIOPMCoreDisplayProgress:
10093 coreDisplayData = data & kIOPMCoreDisplayProgressMask;
10094 break;
10095 case kIOPMCoreGraphicsProgress:
10096 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
10097 break;
10098 default:
10099 return;
10100 }
10101
10102 DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
10103 RTC_TRACE();
10104 }
10105
10106 void
10107 PMTraceWorker::tracePCIPowerChange(
10108 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
10109 {
10110 uint32_t bitMask;
10111 uint32_t expectedFlag;
10112
10113 // Ignore PCI changes outside of system sleep/wake.
10114 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
10115 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
10116 return;
10117 }
10118
10119 // Only record the WillChange transition when going to sleep,
10120 // and the DidChange on the way up.
10121 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
10122 expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
10123 kIOPMDomainWillChange : kIOPMDomainDidChange;
10124 if (changeFlags != expectedFlag) {
10125 return;
10126 }
10127
10128 // Mark this device off in our bitfield
10129 if (bitNum < kPMMaxRTCBitfieldSize) {
10130 bitMask = (1 << bitNum);
10131
10132 if (kPowerChangeStart == type) {
10133 traceData32 |= bitMask;
10134 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
10135 service->getName(), bitNum, bitMask, traceData32);
10136 owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10137 } else {
10138 traceData32 &= ~bitMask;
10139 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10140 service->getName(), bitNum, bitMask, traceData32);
10141 owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10142 }
10143
10144 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10145 RTC_TRACE();
10146 }
10147 }
10148
10149 uint64_t
10150 PMTraceWorker::getPMStatusCode()
10151 {
10152 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10153 }
10154
10155 uint8_t
10156 PMTraceWorker::getTracePhase()
10157 {
10158 return tracePhase;
10159 }
10160
10161 uint32_t
10162 PMTraceWorker::getTraceData()
10163 {
10164 return traceData32;
10165 }
10166
10167 // MARK: -
10168 // MARK: PMHaltWorker
10169
10170 //******************************************************************************
10171 // PMHaltWorker Class
10172 //
10173 //******************************************************************************
10174
10175 PMHaltWorker *
10176 PMHaltWorker::worker( void )
10177 {
10178 PMHaltWorker * me;
10179 IOThread thread;
10180
10181 do {
10182 me = OSTypeAlloc( PMHaltWorker );
10183 if (!me || !me->init()) {
10184 break;
10185 }
10186
10187 me->lock = IOLockAlloc();
10188 if (!me->lock) {
10189 break;
10190 }
10191
10192 DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10193 me->retain(); // thread holds extra retain
10194 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10195 me->release();
10196 break;
10197 }
10198 thread_deallocate(thread);
10199 return me;
10200 } while (false);
10201
10202 if (me) {
10203 me->release();
10204 }
10205 return NULL;
10206 }
10207
10208 void
10209 PMHaltWorker::free( void )
10210 {
10211 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10212 if (lock) {
10213 IOLockFree(lock);
10214 lock = NULL;
10215 }
10216 return OSObject::free();
10217 }
10218
10219 void
10220 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10221 {
10222 PMHaltWorker * me = (PMHaltWorker *) arg;
10223
10224 IOLockLock( gPMHaltLock );
10225 gPMHaltBusyCount++;
10226 me->depth = gPMHaltDepth;
10227 IOLockUnlock( gPMHaltLock );
10228
10229 while (me->depth >= 0) {
10230 PMHaltWorker::work( me );
10231
10232 IOLockLock( gPMHaltLock );
10233 if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10234 // This is the last thread to finish work on this level,
10235 // inform everyone to start working on next lower level.
10236 gPMHaltDepth--;
10237 me->depth = gPMHaltDepth;
10238 gPMHaltIdleCount = 0;
10239 thread_wakeup((event_t) &gPMHaltIdleCount);
10240 } else {
10241 // One or more threads are still working on this level,
10242 // this thread must wait.
10243 me->depth = gPMHaltDepth - 1;
10244 do {
10245 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10246 } while (me->depth != gPMHaltDepth);
10247 }
10248 IOLockUnlock( gPMHaltLock );
10249 }
10250
10251 // No more work to do, terminate thread
10252 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10253 thread_wakeup( &gPMHaltDepth );
10254 me->release();
10255 }
10256
10257 void
10258 PMHaltWorker::work( PMHaltWorker * me )
10259 {
10260 OSSharedPtr<IOService> service;
10261 OSSet * inner;
10262 AbsoluteTime startTime, elapsedTime;
10263 UInt32 deltaTime;
10264 bool timeout;
10265
10266 while (true) {
10267 timeout = false;
10268
10269 // Claim an unit of work from the shared pool
10270 IOLockLock( gPMHaltLock );
10271 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10272 if (inner) {
10273 service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10274 if (service) {
10275 inner->removeObject(service.get());
10276 }
10277 }
10278 IOLockUnlock( gPMHaltLock );
10279 if (!service) {
10280 break; // no more work at this depth
10281 }
10282 clock_get_uptime(&startTime);
10283
10284 if (!service->isInactive() &&
10285 service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10286 IOLockLock(me->lock);
10287 me->startTime = startTime;
10288 me->service = service.get();
10289 me->timeout = false;
10290 IOLockUnlock(me->lock);
10291
10292 service->systemWillShutdown( gPMHaltMessageType);
10293
10294 // Wait for driver acknowledgement
10295 IOLockLock(me->lock);
10296 while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10297 IOLockSleep(me->lock, me, THREAD_UNINT);
10298 }
10299 me->service = NULL;
10300 timeout = me->timeout;
10301 IOLockUnlock(me->lock);
10302 }
10303
10304 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10305 if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10306 LOG("%s driver %s (0x%llx) took %u ms\n",
10307 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10308 "PowerOff" : "Restart",
10309 service->getName(), service->getRegistryEntryID(),
10310 (uint32_t) deltaTime );
10311 halt_log_enter("PowerOff/Restart handler completed",
10312 OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10313 elapsedTime);
10314 }
10315
10316 me->visits++;
10317 }
10318 }
10319
10320 void
10321 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10322 {
10323 UInt64 nano;
10324 AbsoluteTime startTime;
10325 AbsoluteTime endTime;
10326
10327 endTime = *now;
10328
10329 IOLockLock(me->lock);
10330 if (me->service && !me->timeout) {
10331 startTime = me->startTime;
10332 nano = 0;
10333 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10334 SUB_ABSOLUTETIME(&endTime, &startTime);
10335 absolutetime_to_nanoseconds(endTime, &nano);
10336 }
10337 if (nano > 3000000000ULL) {
10338 me->timeout = true;
10339
10340 halt_log_enter("PowerOff/Restart still waiting on handler",
10341 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10342 endTime);
10343 MSG("%s still waiting on %s\n",
10344 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart",
10345 me->service->getName());
10346 }
10347 }
10348 IOLockUnlock(me->lock);
10349 }
10350
10351 //******************************************************************************
10352 // acknowledgeSystemWillShutdown
10353 //
10354 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10355 //******************************************************************************
10356
10357 void
10358 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10359 {
10360 PMHaltWorker * worker;
10361 OSSharedPtr<OSObject> prop;
10362
10363 if (!from) {
10364 return;
10365 }
10366
10367 //DLOG("%s acknowledged\n", from->getName());
10368 prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10369 if (prop) {
10370 worker = (PMHaltWorker *) prop.get();
10371 IOLockLock(worker->lock);
10372 from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10373 thread_wakeup((event_t) worker);
10374 IOLockUnlock(worker->lock);
10375 } else {
10376 DLOG("%s acknowledged without worker property\n",
10377 from->getName());
10378 }
10379 }
10380
10381
10382 //******************************************************************************
10383 // notifySystemShutdown
10384 //
10385 // Notify all objects in PM tree that system will shutdown or restart
10386 //******************************************************************************
10387
10388 static void
10389 notifySystemShutdown( IOService * root, uint32_t messageType )
10390 {
10391 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10392 OSSharedPtr<IORegistryIterator> iter;
10393 IORegistryEntry * entry;
10394 IOService * node;
10395 OSSet * inner;
10396 OSSharedPtr<OSSet> newInner;
10397 PMHaltWorker * workers[kPMHaltMaxWorkers];
10398 AbsoluteTime deadline;
10399 unsigned int totalNodes = 0;
10400 unsigned int depth;
10401 unsigned int rootDepth;
10402 unsigned int numWorkers;
10403 unsigned int count;
10404 int waitResult;
10405 void * baseFunc;
10406 bool ok;
10407
10408 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10409
10410 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10411
10412 // Iterate the entire PM tree starting from root
10413
10414 rootDepth = root->getDepth( gIOPowerPlane );
10415 if (!rootDepth) {
10416 goto done;
10417 }
10418
10419 // debug - for repeated test runs
10420 while (PMHaltWorker::metaClass->getInstanceCount()) {
10421 IOSleep(1);
10422 }
10423
10424 if (!gPMHaltArray) {
10425 gPMHaltArray = OSArray::withCapacity(40);
10426 if (!gPMHaltArray) {
10427 goto done;
10428 }
10429 } else { // debug
10430 gPMHaltArray->flushCollection();
10431 }
10432
10433 if (!gPMHaltLock) {
10434 gPMHaltLock = IOLockAlloc();
10435 if (!gPMHaltLock) {
10436 goto done;
10437 }
10438 }
10439
10440 if (!gPMHaltClientAcknowledgeKey) {
10441 gPMHaltClientAcknowledgeKey =
10442 OSSymbol::withCStringNoCopy("PMShutdown");
10443 if (!gPMHaltClientAcknowledgeKey) {
10444 goto done;
10445 }
10446 }
10447
10448 gPMHaltMessageType = messageType;
10449
10450 // Depth-first walk of PM plane
10451
10452 iter = IORegistryIterator::iterateOver(
10453 root, gIOPowerPlane, kIORegistryIterateRecursively);
10454
10455 if (iter) {
10456 while ((entry = iter->getNextObject())) {
10457 node = OSDynamicCast(IOService, entry);
10458 if (!node) {
10459 continue;
10460 }
10461
10462 if (baseFunc ==
10463 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10464 continue;
10465 }
10466
10467 depth = node->getDepth( gIOPowerPlane );
10468 if (depth <= rootDepth) {
10469 continue;
10470 }
10471
10472 ok = false;
10473
10474 // adjust to zero based depth
10475 depth -= (rootDepth + 1);
10476
10477 // gPMHaltArray is an array of containers, each container
10478 // refers to nodes with the same depth.
10479
10480 count = gPMHaltArray->getCount();
10481 while (depth >= count) {
10482 // expand array and insert placeholders
10483 gPMHaltArray->setObject(PLACEHOLDER);
10484 count++;
10485 }
10486 count = gPMHaltArray->getCount();
10487 if (depth < count) {
10488 inner = (OSSet *)gPMHaltArray->getObject(depth);
10489 if (inner == PLACEHOLDER) {
10490 newInner = OSSet::withCapacity(40);
10491 if (newInner) {
10492 gPMHaltArray->replaceObject(depth, newInner.get());
10493 inner = newInner.get();
10494 }
10495 }
10496
10497 // PM nodes that appear more than once in the tree will have
10498 // the same depth, OSSet will refuse to add the node twice.
10499 if (inner) {
10500 ok = inner->setObject(node);
10501 }
10502 }
10503 if (!ok) {
10504 DLOG("Skipped PM node %s\n", node->getName());
10505 }
10506 }
10507 }
10508
10509 // debug only
10510 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10511 count = 0;
10512 if (inner != PLACEHOLDER) {
10513 count = inner->getCount();
10514 }
10515 DLOG("Nodes at depth %u = %u\n", i, count);
10516 }
10517
10518 // strip placeholders (not all depths are populated)
10519 numWorkers = 0;
10520 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10521 if (inner == PLACEHOLDER) {
10522 gPMHaltArray->removeObject(i);
10523 continue;
10524 }
10525 count = inner->getCount();
10526 if (count > numWorkers) {
10527 numWorkers = count;
10528 }
10529 totalNodes += count;
10530 i++;
10531 }
10532
10533 if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10534 goto done;
10535 }
10536
10537 gPMHaltBusyCount = 0;
10538 gPMHaltIdleCount = 0;
10539 gPMHaltDepth = gPMHaltArray->getCount() - 1;
10540
10541 // Create multiple workers (and threads)
10542
10543 if (numWorkers > kPMHaltMaxWorkers) {
10544 numWorkers = kPMHaltMaxWorkers;
10545 }
10546
10547 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10548 totalNodes, gPMHaltArray->getCount(), numWorkers);
10549
10550 for (unsigned int i = 0; i < numWorkers; i++) {
10551 workers[i] = PMHaltWorker::worker();
10552 }
10553
10554 // Wait for workers to exhaust all available work
10555
10556 IOLockLock(gPMHaltLock);
10557 while (gPMHaltDepth >= 0) {
10558 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10559
10560 waitResult = IOLockSleepDeadline(
10561 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10562 if (THREAD_TIMED_OUT == waitResult) {
10563 AbsoluteTime now;
10564 clock_get_uptime(&now);
10565
10566 IOLockUnlock(gPMHaltLock);
10567 for (unsigned int i = 0; i < numWorkers; i++) {
10568 if (workers[i]) {
10569 PMHaltWorker::checkTimeout(workers[i], &now);
10570 }
10571 }
10572 IOLockLock(gPMHaltLock);
10573 }
10574 }
10575 IOLockUnlock(gPMHaltLock);
10576
10577 // Release all workers
10578
10579 for (unsigned int i = 0; i < numWorkers; i++) {
10580 if (workers[i]) {
10581 workers[i]->release();
10582 }
10583 // worker also retained by it's own thread
10584 }
10585
10586 done:
10587 DLOG("%s done\n", __FUNCTION__);
10588 return;
10589 }
10590
10591 // MARK: -
10592 // MARK: Kernel Assertion
10593
10594 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10595
10596 IOPMDriverAssertionID
10597 IOPMrootDomain::createPMAssertion(
10598 IOPMDriverAssertionType whichAssertionBits,
10599 IOPMDriverAssertionLevel assertionLevel,
10600 IOService *ownerService,
10601 const char *ownerDescription)
10602 {
10603 IOReturn ret;
10604 IOPMDriverAssertionID newAssertion;
10605
10606 if (!pmAssertions) {
10607 return 0;
10608 }
10609
10610 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10611
10612 if (kIOReturnSuccess == ret) {
10613 #if (DEVELOPMENT || DEBUG)
10614 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10615 const char *serviceName = (ownerService && ownerService->reserved) ? ownerService->getName() : NULL;
10616 OSReportWithBacktrace("PMRD: createPMAssertion(0x%qx) %s (%s)", newAssertion,
10617 serviceName, ownerDescription);
10618 }
10619 #endif /* (DEVELOPMENT || DEBUG) */
10620 return newAssertion;
10621 } else {
10622 return 0;
10623 }
10624 }
10625
10626 IOReturn
10627 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10628 {
10629 #if (DEVELOPMENT || DEBUG)
10630 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10631 PMAssertStruct *details = pmAssertions->detailsForID(releaseAssertion, NULL);
10632 if (details) {
10633 const char *serviceName = (details->ownerService && details->ownerService->reserved) ?
10634 details->ownerService->getName() : NULL;
10635 const char *ownerString = details->ownerString ? details->ownerString->getCStringNoCopy() : NULL;
10636 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx) %s (%s)", releaseAssertion, serviceName, ownerString);
10637 } else {
10638 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx)", releaseAssertion);
10639 }
10640 }
10641 #endif /* (DEVELOPMENT || DEBUG) */
10642 if (!pmAssertions) {
10643 return kIOReturnInternalError;
10644 }
10645 return pmAssertions->releaseAssertion(releaseAssertion);
10646 }
10647
10648
10649 IOReturn
10650 IOPMrootDomain::setPMAssertionLevel(
10651 IOPMDriverAssertionID assertionID,
10652 IOPMDriverAssertionLevel assertionLevel)
10653 {
10654 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10655 }
10656
10657 IOPMDriverAssertionLevel
10658 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10659 {
10660 IOPMDriverAssertionType sysLevels;
10661
10662 if (!pmAssertions || whichAssertion == 0) {
10663 return kIOPMDriverAssertionLevelOff;
10664 }
10665
10666 sysLevels = pmAssertions->getActivatedAssertions();
10667
10668 // Check that every bit set in argument 'whichAssertion' is asserted
10669 // in the aggregate bits.
10670 if ((sysLevels & whichAssertion) == whichAssertion) {
10671 return kIOPMDriverAssertionLevelOn;
10672 } else {
10673 return kIOPMDriverAssertionLevelOff;
10674 }
10675 }
10676
10677 IOReturn
10678 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10679 {
10680 if (!pmAssertions) {
10681 return kIOReturnNotFound;
10682 }
10683
10684 return pmAssertions->setUserAssertionLevels(inLevels);
10685 }
10686
10687 IOReturn
10688 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10689 {
10690 return gIOPMWorkLoop->runActionBlock(^{
10691 if (_driverKitMatchingAssertionCount != 0) {
10692 _driverKitMatchingAssertionCount++;
10693 return kIOReturnSuccess;
10694 } else {
10695 if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
10696 // system going to sleep
10697 return kIOReturnBusy;
10698 } else {
10699 // createPMAssertion is asynchronous.
10700 // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10701 // The assertion is used so that on release, we reevaluate all assertions
10702 _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10703 if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10704 _driverKitMatchingAssertionCount = 1;
10705 return kIOReturnSuccess;
10706 } else {
10707 return kIOReturnBusy;
10708 }
10709 }
10710 }
10711 });
10712 }
10713
10714 void
10715 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10716 {
10717 gIOPMWorkLoop->runActionBlock(^{
10718 if (_driverKitMatchingAssertionCount != 0) {
10719 _driverKitMatchingAssertionCount--;
10720 if (_driverKitMatchingAssertionCount == 0) {
10721 releasePMAssertion(_driverKitMatchingAssertion);
10722 _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10723 }
10724 } else {
10725 panic("Over-release of driverkit matching assertion");
10726 }
10727 return kIOReturnSuccess;
10728 });
10729 }
10730
10731 bool
10732 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10733 {
10734 if (pmAssertions) {
10735 pmAssertions->publishProperties();
10736 }
10737 return IOService::serializeProperties(s);
10738 }
10739
10740 OSSharedPtr<OSObject>
10741 IOPMrootDomain::copyProperty( const char * aKey) const
10742 {
10743 OSSharedPtr<OSObject> obj;
10744 obj = IOService::copyProperty(aKey);
10745
10746 if (obj) {
10747 return obj;
10748 }
10749
10750 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10751 sizeof(kIOPMSleepWakeWdogRebootKey))) {
10752 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10753 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10754 } else {
10755 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10756 }
10757 }
10758
10759 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10760 sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10761 if (swd_flags & SWD_VALID_LOGS) {
10762 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10763 } else {
10764 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10765 }
10766 }
10767
10768 /*
10769 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
10770 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10771 * issued by DisplayWrangler on darkwake.
10772 */
10773 if (!strcmp(aKey, "DesktopMode")) {
10774 if (desktopMode) {
10775 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10776 } else {
10777 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10778 }
10779 }
10780 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10781 if (displayIdleForDemandSleep) {
10782 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10783 } else {
10784 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10785 }
10786 }
10787
10788 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10789 OSSharedPtr<OSArray> array;
10790 WAKEEVENT_LOCK();
10791 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10792 OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10793 if (collection) {
10794 array = OSDynamicPtrCast<OSArray>(collection);
10795 }
10796 }
10797 WAKEEVENT_UNLOCK();
10798 return os::move(array);
10799 }
10800
10801 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10802 OSSharedPtr<OSArray> array;
10803 IOLockLock(pmStatsLock);
10804 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10805 OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10806 if (collection) {
10807 array = OSDynamicPtrCast<OSArray>(collection);
10808 }
10809 }
10810 IOLockUnlock(pmStatsLock);
10811 return os::move(array);
10812 }
10813
10814 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10815 OSArray *idleSleepList = NULL;
10816 gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10817 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10818 }
10819
10820 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10821 OSArray *systemSleepList = NULL;
10822 gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10823 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10824 }
10825
10826 if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10827 OSArray *idleSleepList = NULL;
10828 gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10829 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10830 }
10831
10832 if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10833 OSArray *systemSleepList = NULL;
10834 gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10835 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10836 }
10837 return NULL;
10838 }
10839
10840 // MARK: -
10841 // MARK: Wake Event Reporting
10842
10843 void
10844 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10845 {
10846 WAKEEVENT_LOCK();
10847 strlcpy(outBuf, gWakeReasonString, bufSize);
10848 WAKEEVENT_UNLOCK();
10849 }
10850
10851 void
10852 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10853 {
10854 WAKEEVENT_LOCK();
10855 strlcpy(outBuf, gShutdownReasonString, bufSize);
10856 WAKEEVENT_UNLOCK();
10857 }
10858
10859 //******************************************************************************
10860 // acceptSystemWakeEvents
10861 //
10862 // Private control for the acceptance of driver wake event claims.
10863 //******************************************************************************
10864
10865 void
10866 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10867 {
10868 bool logWakeReason = false;
10869
10870 WAKEEVENT_LOCK();
10871 switch (control) {
10872 case kAcceptSystemWakeEvents_Enable:
10873 assert(_acceptSystemWakeEvents == false);
10874 if (!_systemWakeEventsArray) {
10875 _systemWakeEventsArray = OSArray::withCapacity(4);
10876 }
10877 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10878 if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10879 gWakeReasonString[0] = '\0';
10880 if (_systemWakeEventsArray) {
10881 _systemWakeEventsArray->flushCollection();
10882 }
10883 }
10884
10885 // Remove stale WakeType property before system sleep
10886 removeProperty(kIOPMRootDomainWakeTypeKey);
10887 removeProperty(kIOPMRootDomainWakeReasonKey);
10888 break;
10889
10890 case kAcceptSystemWakeEvents_Disable:
10891 _acceptSystemWakeEvents = false;
10892 #if defined(XNU_TARGET_OS_OSX)
10893 logWakeReason = (gWakeReasonString[0] != '\0');
10894 #else /* !defined(XNU_TARGET_OS_OSX) */
10895 logWakeReason = gWakeReasonSysctlRegistered;
10896 #if DEVELOPMENT
10897 static int panic_allowed = -1;
10898
10899 if ((panic_allowed == -1) &&
10900 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10901 panic_allowed = 0;
10902 }
10903
10904 if (panic_allowed) {
10905 size_t i = 0;
10906 // Panic if wake reason is null or empty
10907 for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10908 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10909 break;
10910 }
10911 }
10912 if (i >= strlen(gWakeReasonString)) {
10913 panic("Wake reason is empty");
10914 }
10915 }
10916 #endif /* DEVELOPMENT */
10917 #endif /* !defined(XNU_TARGET_OS_OSX) */
10918
10919 // publish kIOPMRootDomainWakeReasonKey if not already set
10920 if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10921 setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10922 }
10923 break;
10924
10925 case kAcceptSystemWakeEvents_Reenable:
10926 assert(_acceptSystemWakeEvents == false);
10927 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10928 removeProperty(kIOPMRootDomainWakeReasonKey);
10929 break;
10930 }
10931 WAKEEVENT_UNLOCK();
10932
10933 if (logWakeReason) {
10934 MSG("system wake events: %s\n", gWakeReasonString);
10935 }
10936 }
10937
10938 //******************************************************************************
10939 // claimSystemWakeEvent
10940 //
10941 // For a driver to claim a device is the source/conduit of a system wake event.
10942 //******************************************************************************
10943
10944 void
10945 IOPMrootDomain::claimSystemWakeEvent(
10946 IOService * device,
10947 IOOptionBits flags,
10948 const char * reason,
10949 OSObject * details )
10950 {
10951 OSSharedPtr<const OSSymbol> deviceName;
10952 OSSharedPtr<OSNumber> deviceRegId;
10953 OSSharedPtr<OSNumber> claimTime;
10954 OSSharedPtr<OSData> flagsData;
10955 OSSharedPtr<OSString> reasonString;
10956 OSSharedPtr<OSDictionary> dict;
10957 uint64_t timestamp;
10958 bool addWakeReason;
10959
10960 if (!device || !reason) {
10961 return;
10962 }
10963
10964 pmEventTimeStamp(×tamp);
10965
10966 uint64_t args[3] = {};
10967 strlcpy((char *)args, reason, sizeof(args));
10968 kdebugTrace(kPMLogClaimSystemWake, args[0], args[1], args[2], device->getRegistryEntryID());
10969
10970 IOOptionBits aotFlags = 0;
10971 bool needAOTEvaluate = FALSE;
10972
10973 if (kIOPMAOTModeAddEventFlags & _aotMode) {
10974 // Only allow lingering in AOT_STATE for the two wake reasons used for the wrist raise gesture.
10975 if (strcmp("AOP.OutboxNotEmpty", reason) && strcmp("spu_gesture", reason)) {
10976 flags |= kIOPMWakeEventAOTExit;
10977 }
10978 }
10979
10980 #if DEVELOPMENT || DEBUG
10981 if (_aotLingerTime && !strcmp("rtc", reason)) {
10982 flags |= kIOPMWakeEventAOTPossibleExit;
10983 }
10984 #endif /* DEVELOPMENT || DEBUG */
10985
10986 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10987 // Publishing the WakeType is serialized by the PM work loop
10988 if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
10989 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10990 (void *) _nextScheduledAlarmType.get());
10991 }
10992
10993 // Workaround for the missing wake HID event
10994 if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
10995 if (!strcmp("trackpadkeyboard", reason)) {
10996 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10997 (void *) gIOPMWakeTypeUserKey.get());
10998 }
10999 }
11000 #endif
11001
11002 deviceName = device->copyName(gIOServicePlane);
11003 deviceRegId = OSNumber::withNumber(device->getRegistryEntryID(), 64);
11004 claimTime = OSNumber::withNumber(timestamp, 64);
11005 flagsData = OSData::withValue(flags);
11006 reasonString = OSString::withCString(reason);
11007 dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
11008 if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
11009 goto done;
11010 }
11011
11012 dict->setObject(gIONameKey, deviceName.get());
11013 dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
11014 dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
11015 dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
11016 dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
11017 if (details) {
11018 dict->setObject(kIOPMWakeEventDetailsKey, details);
11019 }
11020
11021 WAKEEVENT_LOCK();
11022 addWakeReason = _acceptSystemWakeEvents;
11023 if (_aotMode) {
11024 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
11025 }
11026 aotFlags = (kIOPMWakeEventAOTFlags & flags);
11027 aotFlags = (aotFlags & ~_aotPendingFlags);
11028 needAOTEvaluate = false;
11029 if (_aotNow && aotFlags) {
11030 if (kIOPMWakeEventAOTPossibleExit & flags) {
11031 _aotMetrics->possibleCount++;
11032 }
11033 if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
11034 _aotMetrics->confirmedPossibleCount++;
11035 }
11036 if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
11037 _aotMetrics->rejectedPossibleCount++;
11038 }
11039 if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
11040 _aotMetrics->expiredPossibleCount++;
11041 }
11042
11043 _aotPendingFlags |= aotFlags;
11044 addWakeReason = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
11045 needAOTEvaluate = _aotReadyToFullWake;
11046 }
11047 DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
11048 reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
11049 _aotNow, pmTracer->getTracePhase(), addWakeReason);
11050
11051 #if DEVELOPMENT || DEBUG
11052 if (addWakeReason) {
11053 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11054 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11055 "Report System Wake Event",
11056 "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
11057 reason,
11058 (int)flags,
11059 deviceName->getCStringNoCopy(),
11060 device->getRegistryEntryID()
11061 );
11062 }
11063 #endif /* DEVELOPMENT || DEBUG */
11064
11065 if (!gWakeReasonSysctlRegistered) {
11066 // Lazy registration until the platform driver stops registering
11067 // the same name.
11068 gWakeReasonSysctlRegistered = true;
11069 }
11070 if (addWakeReason) {
11071 _systemWakeEventsArray->setObject(dict.get());
11072 if (gWakeReasonString[0] != '\0') {
11073 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
11074 }
11075 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
11076 }
11077
11078 WAKEEVENT_UNLOCK();
11079 if (needAOTEvaluate) {
11080 // Call aotEvaluate() on PM work loop since it may call
11081 // aotExit() which accesses PM state.
11082 pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
11083 }
11084
11085 done:
11086 return;
11087 }
11088
11089 //******************************************************************************
11090 // claimSystemBootEvent
11091 //
11092 // For a driver to claim a device is the source/conduit of a system boot event.
11093 //******************************************************************************
11094
11095 void
11096 IOPMrootDomain::claimSystemBootEvent(
11097 IOService * device,
11098 IOOptionBits flags,
11099 const char * reason,
11100 __unused OSObject * details )
11101 {
11102 if (!device || !reason) {
11103 return;
11104 }
11105
11106 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11107 #if DEVELOPMENT || DEBUG
11108 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11109 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11110 "Report System Boot Device",
11111 "Reason: %s Flags: 0x%x Device: %s",
11112 reason,
11113 (int)flags,
11114 device->getName()
11115 );
11116 #endif /* DEVELOPMENT || DEBUG */
11117 WAKEEVENT_LOCK();
11118 if (!gBootReasonSysctlRegistered) {
11119 // Lazy sysctl registration after setting gBootReasonString
11120 strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
11121 os_atomic_store(&gBootReasonSysctlRegistered, true, release);
11122 }
11123 WAKEEVENT_UNLOCK();
11124 }
11125
11126 //******************************************************************************
11127 // claimSystemShutdownEvent
11128 //
11129 // For drivers to claim a system shutdown event on the ensuing boot.
11130 //******************************************************************************
11131
11132 void
11133 IOPMrootDomain::claimSystemShutdownEvent(
11134 IOService * device,
11135 IOOptionBits flags,
11136 const char * reason,
11137 __unused OSObject * details )
11138 {
11139 if (!device || !reason) {
11140 return;
11141 }
11142
11143 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11144 #if DEVELOPMENT || DEBUG
11145 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11146 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11147 "Report System Shutdown Cause From Previous Boot",
11148 "Reason: %s Flags: 0x%x Device: %s",
11149 reason,
11150 (int)flags,
11151 device->getName()
11152 );
11153 #endif /* DEVELOPMENT || DEBUG */
11154 WAKEEVENT_LOCK();
11155 if (gShutdownReasonString[0] != '\0') {
11156 strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11157 }
11158 strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11159
11160 gShutdownReasonSysctlRegistered = true;
11161 WAKEEVENT_UNLOCK();
11162 }
11163
11164 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11165
11166 // MARK: -
11167 // MARK: PMSettingHandle
11168
11169 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11170
11171 void
11172 PMSettingHandle::free( void )
11173 {
11174 if (pmso) {
11175 pmso->clientHandleFreed();
11176 pmso->release();
11177 pmso = NULL;
11178 }
11179
11180 OSObject::free();
11181 }
11182
11183 // MARK: -
11184 // MARK: PMSettingObject
11185
11186 #undef super
11187 #define super OSObject
11188 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11189
11190 /*
11191 * Static constructor/initializer for PMSettingObject
11192 */
11193 PMSettingObject *PMSettingObject::pmSettingObject(
11194 IOPMrootDomain * parent_arg,
11195 IOPMSettingControllerCallback handler_arg,
11196 OSObject * target_arg,
11197 uintptr_t refcon_arg,
11198 uint32_t supportedPowerSources,
11199 const OSSymbol * settings[],
11200 OSObject * *handle_obj)
11201 {
11202 uint32_t settingCount = 0;
11203 PMSettingObject *pmso = NULL;
11204 PMSettingHandle *pmsh = NULL;
11205
11206 if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11207 return NULL;
11208 }
11209
11210 // count OSSymbol entries in NULL terminated settings array
11211 while (settings[settingCount]) {
11212 settingCount++;
11213 }
11214 if (0 == settingCount) {
11215 return NULL;
11216 }
11217
11218 pmso = new PMSettingObject;
11219 if (!pmso || !pmso->init()) {
11220 goto fail;
11221 }
11222
11223 pmsh = new PMSettingHandle;
11224 if (!pmsh || !pmsh->init()) {
11225 goto fail;
11226 }
11227
11228 queue_init(&pmso->calloutQueue);
11229 pmso->parent = parent_arg;
11230 pmso->func = handler_arg;
11231 pmso->target = target_arg;
11232 pmso->refcon = refcon_arg;
11233 pmso->settingCount = settingCount;
11234
11235 pmso->retain(); // handle holds a retain on pmso
11236 pmsh->pmso = pmso;
11237 pmso->pmsh = pmsh;
11238
11239 pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11240 if (pmso->publishedFeatureID) {
11241 for (unsigned int i = 0; i < settingCount; i++) {
11242 // Since there is now at least one listener to this setting, publish
11243 // PM root domain support for it.
11244 parent_arg->publishPMSetting( settings[i],
11245 supportedPowerSources, &pmso->publishedFeatureID[i] );
11246 }
11247 }
11248
11249 *handle_obj = pmsh;
11250 return pmso;
11251
11252 fail:
11253 if (pmso) {
11254 pmso->release();
11255 }
11256 if (pmsh) {
11257 pmsh->release();
11258 }
11259 return NULL;
11260 }
11261
11262 void
11263 PMSettingObject::free( void )
11264 {
11265 if (publishedFeatureID) {
11266 for (const auto& featureID : publishedFeatureID) {
11267 if (featureID) {
11268 parent->removePublishedFeature( featureID );
11269 }
11270 }
11271
11272 publishedFeatureID = {};
11273 }
11274
11275 super::free();
11276 }
11277
11278 IOReturn
11279 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11280 {
11281 return (*func)(target, type, object, refcon);
11282 }
11283
11284 void
11285 PMSettingObject::clientHandleFreed( void )
11286 {
11287 parent->deregisterPMSettingObject(this);
11288 }
11289
11290 // MARK: -
11291 // MARK: PMAssertionsTracker
11292
11293 //*********************************************************************************
11294 //*********************************************************************************
11295 //*********************************************************************************
11296 // class PMAssertionsTracker Implementation
11297
11298 #define kAssertUniqueIDStart 500
11299
11300 PMAssertionsTracker *
11301 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11302 {
11303 PMAssertionsTracker *me;
11304
11305 me = new PMAssertionsTracker;
11306 if (!me || !me->init()) {
11307 if (me) {
11308 me->release();
11309 }
11310 return NULL;
11311 }
11312
11313 me->owner = rootDomain;
11314 me->issuingUniqueID = kAssertUniqueIDStart;
11315 me->assertionsArray = OSArray::withCapacity(5);
11316 me->assertionsKernel = 0;
11317 me->assertionsUser = 0;
11318 me->assertionsCombined = 0;
11319 me->assertionsArrayLock = IOLockAlloc();
11320 me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11321
11322 assert(me->assertionsArray);
11323 assert(me->assertionsArrayLock);
11324
11325 return me;
11326 }
11327
11328 /* tabulate
11329 * - Update assertionsKernel to reflect the state of all
11330 * assertions in the kernel.
11331 * - Update assertionsCombined to reflect both kernel & user space.
11332 */
11333 void
11334 PMAssertionsTracker::tabulate(void)
11335 {
11336 int i;
11337 int count;
11338 const PMAssertStruct *_a = nullptr;
11339 OSValueObject<PMAssertStruct> *_d = nullptr;
11340
11341 IOPMDriverAssertionType oldKernel = assertionsKernel;
11342 IOPMDriverAssertionType oldCombined = assertionsCombined;
11343
11344 ASSERT_GATED();
11345
11346 assertionsKernel = 0;
11347 assertionsCombined = 0;
11348
11349 if (!assertionsArray) {
11350 return;
11351 }
11352
11353 if ((count = assertionsArray->getCount())) {
11354 for (i = 0; i < count; i++) {
11355 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11356 if (_d) {
11357 _a = _d->getBytesNoCopy();
11358 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11359 assertionsKernel |= _a->assertionBits;
11360 }
11361 }
11362 }
11363 }
11364
11365 tabulateProducerCount++;
11366 assertionsCombined = assertionsKernel | assertionsUser;
11367
11368 if ((assertionsKernel != oldKernel) ||
11369 (assertionsCombined != oldCombined)) {
11370 owner->evaluateAssertions(assertionsCombined, oldCombined);
11371 }
11372 }
11373
11374 void
11375 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11376 {
11377 AbsoluteTime now;
11378 uint64_t nsec;
11379
11380 if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11381 (assertStruct->assertCPUStartTime == 0)) {
11382 return;
11383 }
11384
11385 now = mach_absolute_time();
11386 SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11387 absolutetime_to_nanoseconds(now, &nsec);
11388 assertStruct->assertCPUDuration += nsec;
11389 assertStruct->assertCPUStartTime = 0;
11390
11391 if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11392 maxAssertCPUDuration = assertStruct->assertCPUDuration;
11393 maxAssertCPUEntryId = assertStruct->registryEntryID;
11394 }
11395 }
11396
11397 void
11398 PMAssertionsTracker::reportCPUBitAccounting( void )
11399 {
11400 const PMAssertStruct *_a = nullptr;
11401 OSValueObject<PMAssertStruct> *_d = nullptr;
11402 int i, count;
11403 AbsoluteTime now;
11404 uint64_t nsec;
11405
11406 ASSERT_GATED();
11407
11408 // Account for drivers that are still holding the CPU assertion
11409 if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11410 now = mach_absolute_time();
11411 if ((count = assertionsArray->getCount())) {
11412 for (i = 0; i < count; i++) {
11413 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11414 if (_d) {
11415 _a = _d->getBytesNoCopy();
11416 if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11417 (_a->level == kIOPMDriverAssertionLevelOn) &&
11418 (_a->assertCPUStartTime != 0)) {
11419 // Don't modify PMAssertStruct, leave that
11420 // for updateCPUBitAccounting()
11421 SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11422 absolutetime_to_nanoseconds(now, &nsec);
11423 nsec += _a->assertCPUDuration;
11424 if (nsec > maxAssertCPUDuration) {
11425 maxAssertCPUDuration = nsec;
11426 maxAssertCPUEntryId = _a->registryEntryID;
11427 }
11428 }
11429 }
11430 }
11431 }
11432 }
11433
11434 if (maxAssertCPUDuration) {
11435 DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11436 (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11437 }
11438
11439 maxAssertCPUDuration = 0;
11440 maxAssertCPUEntryId = 0;
11441 }
11442
11443 void
11444 PMAssertionsTracker::publishProperties( void )
11445 {
11446 OSSharedPtr<OSArray> assertionsSummary;
11447
11448 if (tabulateConsumerCount != tabulateProducerCount) {
11449 IOLockLock(assertionsArrayLock);
11450
11451 tabulateConsumerCount = tabulateProducerCount;
11452
11453 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11454 */
11455 assertionsSummary = copyAssertionsArray();
11456 if (assertionsSummary) {
11457 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11458 } else {
11459 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11460 }
11461
11462 /* Publish the IOPMrootDomain property "DriverPMAssertions"
11463 */
11464 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11465
11466 IOLockUnlock(assertionsArrayLock);
11467 }
11468 }
11469
11470 PMAssertStruct *
11471 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11472 {
11473 PMAssertStruct *_a = NULL;
11474 OSValueObject<PMAssertStruct> *_d = nullptr;
11475 int found = -1;
11476 int count = 0;
11477 int i = 0;
11478
11479 if (assertionsArray
11480 && (count = assertionsArray->getCount())) {
11481 for (i = 0; i < count; i++) {
11482 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11483 if (_d) {
11484 _a = _d->getMutableBytesNoCopy();
11485 if (_a && (_id == _a->id)) {
11486 found = i;
11487 break;
11488 }
11489 }
11490 }
11491 }
11492
11493 if (-1 == found) {
11494 return NULL;
11495 } else {
11496 if (index) {
11497 *index = found;
11498 }
11499 return _a;
11500 }
11501 }
11502
11503 /* PMAssertionsTracker::handleCreateAssertion
11504 * Perform assertion work on the PM workloop. Do not call directly.
11505 */
11506 IOReturn
11507 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11508 {
11509 PMAssertStruct *assertStruct = nullptr;
11510
11511 ASSERT_GATED();
11512
11513 if (newAssertion) {
11514 IOLockLock(assertionsArrayLock);
11515 assertStruct = newAssertion->getMutableBytesNoCopy();
11516 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11517 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11518 assertStruct->assertCPUStartTime = mach_absolute_time();
11519 }
11520 assertionsArray->setObject(newAssertion);
11521 IOLockUnlock(assertionsArrayLock);
11522 newAssertion->release();
11523
11524 tabulate();
11525 }
11526 return kIOReturnSuccess;
11527 }
11528
11529 /* PMAssertionsTracker::createAssertion
11530 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11531 * appropiate.
11532 */
11533 IOReturn
11534 PMAssertionsTracker::createAssertion(
11535 IOPMDriverAssertionType which,
11536 IOPMDriverAssertionLevel level,
11537 IOService *serviceID,
11538 const char *whoItIs,
11539 IOPMDriverAssertionID *outID)
11540 {
11541 OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11542 PMAssertStruct track;
11543
11544 // Warning: trillions and trillions of created assertions may overflow the unique ID.
11545 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11546 track.level = level;
11547 track.assertionBits = which;
11548
11549 // NB: ownerString is explicitly managed by PMAssertStruct
11550 // it will be released in `handleReleaseAssertion' below
11551 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11552 track.ownerService = serviceID;
11553 track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11554 track.modifiedTime = 0;
11555 pmEventTimeStamp(&track.createdTime);
11556 track.assertCPUStartTime = 0;
11557 track.assertCPUDuration = 0;
11558
11559 dataStore = OSValueObjectWithValue(track);
11560 if (!dataStore) {
11561 if (track.ownerString) {
11562 track.ownerString->release();
11563 track.ownerString = NULL;
11564 }
11565 return kIOReturnNoMemory;
11566 }
11567
11568 *outID = track.id;
11569
11570 if (owner && owner->pmPowerStateQueue) {
11571 // queue action is responsible for releasing dataStore
11572 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11573 }
11574
11575 return kIOReturnSuccess;
11576 }
11577
11578 /* PMAssertionsTracker::handleReleaseAssertion
11579 * Runs in PM workloop. Do not call directly.
11580 */
11581 IOReturn
11582 PMAssertionsTracker::handleReleaseAssertion(
11583 IOPMDriverAssertionID _id)
11584 {
11585 ASSERT_GATED();
11586
11587 int index;
11588 PMAssertStruct *assertStruct = detailsForID(_id, &index);
11589
11590 if (!assertStruct) {
11591 return kIOReturnNotFound;
11592 }
11593
11594 IOLockLock(assertionsArrayLock);
11595
11596 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11597 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11598 updateCPUBitAccounting(assertStruct);
11599 }
11600
11601 if (assertStruct->ownerString) {
11602 assertStruct->ownerString->release();
11603 assertStruct->ownerString = NULL;
11604 }
11605
11606 assertionsArray->removeObject(index);
11607 IOLockUnlock(assertionsArrayLock);
11608
11609 tabulate();
11610 return kIOReturnSuccess;
11611 }
11612
11613 /* PMAssertionsTracker::releaseAssertion
11614 * Releases an assertion and affects system behavior if appropiate.
11615 * Actual work happens on PM workloop.
11616 */
11617 IOReturn
11618 PMAssertionsTracker::releaseAssertion(
11619 IOPMDriverAssertionID _id)
11620 {
11621 if (owner && owner->pmPowerStateQueue) {
11622 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11623 }
11624 return kIOReturnSuccess;
11625 }
11626
11627 /* PMAssertionsTracker::handleSetAssertionLevel
11628 * Runs in PM workloop. Do not call directly.
11629 */
11630 IOReturn
11631 PMAssertionsTracker::handleSetAssertionLevel(
11632 IOPMDriverAssertionID _id,
11633 IOPMDriverAssertionLevel _level)
11634 {
11635 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
11636
11637 ASSERT_GATED();
11638
11639 if (!assertStruct) {
11640 return kIOReturnNotFound;
11641 }
11642
11643 IOLockLock(assertionsArrayLock);
11644 pmEventTimeStamp(&assertStruct->modifiedTime);
11645 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11646 (assertStruct->level != _level)) {
11647 if (_level == kIOPMDriverAssertionLevelOn) {
11648 assertStruct->assertCPUStartTime = mach_absolute_time();
11649 } else {
11650 updateCPUBitAccounting(assertStruct);
11651 }
11652 }
11653 assertStruct->level = _level;
11654 IOLockUnlock(assertionsArrayLock);
11655
11656 tabulate();
11657 return kIOReturnSuccess;
11658 }
11659
11660 /* PMAssertionsTracker::setAssertionLevel
11661 */
11662 IOReturn
11663 PMAssertionsTracker::setAssertionLevel(
11664 IOPMDriverAssertionID _id,
11665 IOPMDriverAssertionLevel _level)
11666 {
11667 if (owner && owner->pmPowerStateQueue) {
11668 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11669 (void *)(uintptr_t)_level, _id);
11670 }
11671
11672 return kIOReturnSuccess;
11673 }
11674
11675 IOReturn
11676 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11677 {
11678 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11679
11680 ASSERT_GATED();
11681
11682 if (new_user_levels != assertionsUser) {
11683 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11684 assertionsUser = new_user_levels;
11685 }
11686
11687 tabulate();
11688 return kIOReturnSuccess;
11689 }
11690
11691 IOReturn
11692 PMAssertionsTracker::setUserAssertionLevels(
11693 IOPMDriverAssertionType new_user_levels)
11694 {
11695 if (gIOPMWorkLoop) {
11696 gIOPMWorkLoop->runAction(
11697 OSMemberFunctionCast(
11698 IOWorkLoop::Action,
11699 this,
11700 &PMAssertionsTracker::handleSetUserAssertionLevels),
11701 this,
11702 (void *) &new_user_levels, NULL, NULL, NULL);
11703 }
11704
11705 return kIOReturnSuccess;
11706 }
11707
11708
11709 OSSharedPtr<OSArray>
11710 PMAssertionsTracker::copyAssertionsArray(void)
11711 {
11712 int count;
11713 int i;
11714 OSSharedPtr<OSArray> outArray = NULL;
11715
11716 if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11717 goto exit;
11718 }
11719 outArray = OSArray::withCapacity(count);
11720 if (!outArray) {
11721 goto exit;
11722 }
11723
11724 for (i = 0; i < count; i++) {
11725 const PMAssertStruct *_a = nullptr;
11726 OSValueObject<PMAssertStruct> *_d = nullptr;
11727 OSSharedPtr<OSDictionary> details;
11728
11729 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11730 if (_d && (_a = _d->getBytesNoCopy())) {
11731 OSSharedPtr<OSNumber> _n;
11732
11733 details = OSDictionary::withCapacity(7);
11734 if (!details) {
11735 continue;
11736 }
11737
11738 outArray->setObject(details.get());
11739
11740 _n = OSNumber::withNumber(_a->id, 64);
11741 if (_n) {
11742 details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11743 }
11744 _n = OSNumber::withNumber(_a->createdTime, 64);
11745 if (_n) {
11746 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11747 }
11748 _n = OSNumber::withNumber(_a->modifiedTime, 64);
11749 if (_n) {
11750 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11751 }
11752 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11753 if (_n) {
11754 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11755 }
11756 _n = OSNumber::withNumber(_a->level, 64);
11757 if (_n) {
11758 details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11759 }
11760 _n = OSNumber::withNumber(_a->assertionBits, 64);
11761 if (_n) {
11762 details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11763 }
11764
11765 if (_a->ownerString) {
11766 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11767 }
11768 }
11769 }
11770
11771 exit:
11772 return os::move(outArray);
11773 }
11774
11775 IOPMDriverAssertionType
11776 PMAssertionsTracker::getActivatedAssertions(void)
11777 {
11778 return assertionsCombined;
11779 }
11780
11781 IOPMDriverAssertionLevel
11782 PMAssertionsTracker::getAssertionLevel(
11783 IOPMDriverAssertionType type)
11784 {
11785 // FIXME: unused and also wrong
11786 if (type && ((type & assertionsKernel) == assertionsKernel)) {
11787 return kIOPMDriverAssertionLevelOn;
11788 } else {
11789 return kIOPMDriverAssertionLevelOff;
11790 }
11791 }
11792
11793 //*********************************************************************************
11794 //*********************************************************************************
11795 //*********************************************************************************
11796
11797
11798 static void
11799 pmEventTimeStamp(uint64_t *recordTS)
11800 {
11801 clock_sec_t tsec;
11802 clock_usec_t tusec;
11803
11804 if (!recordTS) {
11805 return;
11806 }
11807
11808 // We assume tsec fits into 32 bits; 32 bits holds enough
11809 // seconds for 136 years since the epoch in 1970.
11810 clock_get_calendar_microtime(&tsec, &tusec);
11811
11812
11813 // Pack the sec & microsec calendar time into a uint64_t, for fun.
11814 *recordTS = 0;
11815 *recordTS |= (uint32_t)tusec;
11816 *recordTS |= ((uint64_t)tsec << 32);
11817
11818 return;
11819 }
11820
11821 // MARK: -
11822 // MARK: IORootParent
11823
11824 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11825
11826 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11827
11828 // The reason that root domain needs a root parent is to facilitate demand
11829 // sleep, since a power change from the root parent cannot be vetoed.
11830 //
11831 // The above statement is no longer true since root domain now performs
11832 // demand sleep using overrides. But root parent remains to avoid changing
11833 // the power tree stacking. Root parent is parked at the max power state.
11834
11835
11836 static IOPMPowerState patriarchPowerStates[2] =
11837 {
11838 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11839 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11840 };
11841
11842 void
11843 IORootParent::initialize( void )
11844 {
11845
11846 gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
11847 gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
11848 gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
11849 gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
11850 gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
11851 gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
11852 gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
11853 gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
11854 gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
11855 gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
11856 gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
11857 gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
11858 gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
11859 gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
11860 gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
11861 gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
11862 gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
11863 gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
11864 gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
11865 gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
11866 gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
11867 gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
11868 gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
11869 gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
11870 gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
11871 gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
11872 gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
11873 gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
11874 gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
11875 gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
11876 gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
11877 gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
11878 gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
11879 gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
11880 gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
11881 gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
11882 gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
11883 gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
11884 gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
11885 gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
11886 gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
11887 gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
11888 gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
11889 gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
11890 }
11891
11892 bool
11893 IORootParent::start( IOService * nub )
11894 {
11895 IOService::start(nub);
11896 attachToParent( getRegistryRoot(), gIOPowerPlane );
11897 PMinit();
11898 registerPowerDriver(this, patriarchPowerStates, 2);
11899 makeUsable();
11900 return true;
11901 }
11902
11903 void
11904 IORootParent::shutDownSystem( void )
11905 {
11906 }
11907
11908 void
11909 IORootParent::restartSystem( void )
11910 {
11911 }
11912
11913 void
11914 IORootParent::sleepSystem( void )
11915 {
11916 }
11917
11918 void
11919 IORootParent::dozeSystem( void )
11920 {
11921 }
11922
11923 void
11924 IORootParent::sleepToDoze( void )
11925 {
11926 }
11927
11928 void
11929 IORootParent::wakeSystem( void )
11930 {
11931 }
11932
11933 OSSharedPtr<OSObject>
11934 IORootParent::copyProperty( const char * aKey) const
11935 {
11936 return IOService::copyProperty(aKey);
11937 }
11938
11939 uint32_t
11940 IOPMrootDomain::getWatchdogTimeout()
11941 {
11942 if (gSwdSleepWakeTimeout) {
11943 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11944 }
11945 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11946 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11947 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11948 } else {
11949 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11950 }
11951 }
11952
11953
11954 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11955 IOReturn
11956 IOPMrootDomain::restartWithStackshot()
11957 {
11958 takeStackshot(true);
11959
11960 return kIOReturnSuccess;
11961 }
11962
11963 void
11964 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
11965 {
11966 takeStackshot(wdogTrigger);
11967 }
11968
11969 void
11970 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
11971 {
11972 switch (tracePhase) {
11973 case kIOPMTracePointSleepStarted:
11974 *phaseString = "kIOPMTracePointSleepStarted";
11975 *description = "starting sleep";
11976 break;
11977
11978 case kIOPMTracePointSleepApplications:
11979 *phaseString = "kIOPMTracePointSleepApplications";
11980 *description = "notifying applications";
11981 break;
11982
11983 case kIOPMTracePointSleepPriorityClients:
11984 *phaseString = "kIOPMTracePointSleepPriorityClients";
11985 *description = "notifying clients about upcoming system capability changes";
11986 break;
11987
11988 case kIOPMTracePointSleepWillChangeInterests:
11989 *phaseString = "kIOPMTracePointSleepWillChangeInterests";
11990 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11991 break;
11992
11993 case kIOPMTracePointSleepPowerPlaneDrivers:
11994 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
11995 *description = "calling power state change callbacks";
11996 break;
11997
11998 case kIOPMTracePointSleepDidChangeInterests:
11999 *phaseString = "kIOPMTracePointSleepDidChangeInterests";
12000 *description = "calling rootDomain's clients about rootDomain's state changes";
12001 break;
12002
12003 case kIOPMTracePointSleepCapabilityClients:
12004 *phaseString = "kIOPMTracePointSleepCapabilityClients";
12005 *description = "notifying clients about current system capabilities";
12006 break;
12007
12008 case kIOPMTracePointSleepPlatformActions:
12009 *phaseString = "kIOPMTracePointSleepPlatformActions";
12010 *description = "calling Quiesce/Sleep action callbacks";
12011 break;
12012
12013 case kIOPMTracePointSleepCPUs:
12014 {
12015 *phaseString = "kIOPMTracePointSleepCPUs";
12016 #if defined(__i386__) || defined(__x86_64__)
12017 /*
12018 * We cannot use the getCPUNumber() method to get the cpu number, since
12019 * that cpu number is unrelated to the cpu number we need (we need the cpu
12020 * number as enumerated by the scheduler, NOT the CPU number enumerated
12021 * by ACPIPlatform as the CPUs are enumerated in MADT order).
12022 * Instead, pass the Mach processor pointer associated with the current
12023 * shutdown target so its associated cpu_id can be used in
12024 * processor_to_datastring.
12025 */
12026 if (currentShutdownTarget != NULL &&
12027 currentShutdownTarget->getMachProcessor() != NULL) {
12028 const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
12029 currentShutdownTarget->getMachProcessor());
12030 *description = sbuf;
12031 } else {
12032 *description = "halting all non-boot CPUs";
12033 }
12034 #else
12035 *description = "halting all non-boot CPUs";
12036 #endif
12037 break;
12038 }
12039 case kIOPMTracePointSleepPlatformDriver:
12040 *phaseString = "kIOPMTracePointSleepPlatformDriver";
12041 *description = "executing platform specific code";
12042 break;
12043
12044 case kIOPMTracePointHibernate:
12045 *phaseString = "kIOPMTracePointHibernate";
12046 *description = "writing the hibernation image";
12047 break;
12048
12049 case kIOPMTracePointSystemSleep:
12050 *phaseString = "kIOPMTracePointSystemSleep";
12051 *description = "in EFI/Bootrom after last point of entry to sleep";
12052 break;
12053
12054 case kIOPMTracePointWakePlatformDriver:
12055 *phaseString = "kIOPMTracePointWakePlatformDriver";
12056 *description = "executing platform specific code";
12057 break;
12058
12059
12060 case kIOPMTracePointWakePlatformActions:
12061 *phaseString = "kIOPMTracePointWakePlatformActions";
12062 *description = "calling Wake action callbacks";
12063 break;
12064
12065 case kIOPMTracePointWakeCPUs:
12066 *phaseString = "kIOPMTracePointWakeCPUs";
12067 *description = "starting non-boot CPUs";
12068 break;
12069
12070 case kIOPMTracePointWakeWillPowerOnClients:
12071 *phaseString = "kIOPMTracePointWakeWillPowerOnClients";
12072 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
12073 break;
12074
12075 case kIOPMTracePointWakeWillChangeInterests:
12076 *phaseString = "kIOPMTracePointWakeWillChangeInterests";
12077 *description = "calling rootDomain's clients about upcoming rootDomain's state changes";
12078 break;
12079
12080 case kIOPMTracePointWakeDidChangeInterests:
12081 *phaseString = "kIOPMTracePointWakeDidChangeInterests";
12082 *description = "calling rootDomain's clients about completed rootDomain's state changes";
12083 break;
12084
12085 case kIOPMTracePointWakePowerPlaneDrivers:
12086 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
12087 *description = "calling power state change callbacks";
12088 break;
12089
12090 case kIOPMTracePointWakeCapabilityClients:
12091 *phaseString = "kIOPMTracePointWakeCapabilityClients";
12092 *description = "informing clients about current system capabilities";
12093 break;
12094
12095 case kIOPMTracePointWakeApplications:
12096 *phaseString = "kIOPMTracePointWakeApplications";
12097 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
12098 break;
12099
12100 case kIOPMTracePointDarkWakeEntry:
12101 *phaseString = "kIOPMTracePointDarkWakeEntry";
12102 *description = "entering darkwake on way to sleep";
12103 break;
12104
12105 case kIOPMTracePointDarkWakeExit:
12106 *phaseString = "kIOPMTracePointDarkWakeExit";
12107 *description = "entering fullwake from darkwake";
12108 break;
12109
12110 default:
12111 *phaseString = NULL;
12112 *description = NULL;
12113 }
12114 }
12115
12116 void
12117 IOPMrootDomain::saveFailureData2File()
12118 {
12119 unsigned int len = 0;
12120 char failureStr[512];
12121 errno_t error;
12122 char *outbuf;
12123 OSNumber *statusCode;
12124 uint64_t pmStatusCode = 0;
12125 uint32_t phaseData = 0;
12126 uint32_t phaseDetail = 0;
12127 bool efiFailure = false;
12128
12129 OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
12130 statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
12131 if (statusCode) {
12132 pmStatusCode = statusCode->unsigned64BitValue();
12133 phaseData = pmStatusCode & 0xFFFFFFFF;
12134 phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
12135 if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
12136 LOG("Sleep Wake failure in EFI\n");
12137 efiFailure = true;
12138 failureStr[0] = 0;
12139 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);
12140 len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12141 }
12142 }
12143
12144 if (!efiFailure) {
12145 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12146 swd_flags |= SWD_BOOT_BY_SW_WDOG;
12147 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12148 // dump panic will handle saving nvram data
12149 return;
12150 }
12151
12152 /* Keeping this around for capturing data during power
12153 * button press */
12154
12155 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12156 DLOG("No sleep wake failure string\n");
12157 return;
12158 }
12159 if (len == 0) {
12160 DLOG("Ignoring zero byte SleepWake failure string\n");
12161 goto exit;
12162 }
12163
12164 // if PMStatus code is zero, delete stackshot and return
12165 if (statusCode) {
12166 if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12167 // there was no sleep wake failure
12168 // this can happen if delete stackshot was called
12169 // before take stackshot completed. Let us delete any
12170 // sleep wake failure data in nvram
12171 DLOG("Deleting stackshot on successful wake\n");
12172 deleteStackshot();
12173 return;
12174 }
12175 }
12176
12177 if (len > sizeof(failureStr)) {
12178 len = sizeof(failureStr);
12179 }
12180 failureStr[0] = 0;
12181 PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12182 }
12183 if (failureStr[0] != 0) {
12184 error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12185 if (error) {
12186 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12187 } else {
12188 DLOG("Saved SleepWake failure string to file.\n");
12189 }
12190 }
12191
12192 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12193 goto exit;
12194 }
12195
12196 if (swd_buffer) {
12197 unsigned int len = 0;
12198 errno_t error;
12199 char nvram_var_name_buffer[20];
12200 unsigned int concat_len = 0;
12201 swd_hdr *hdr = NULL;
12202
12203
12204 hdr = (swd_hdr *)swd_buffer;
12205 outbuf = (char *)hdr + hdr->spindump_offset;
12206 OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12207
12208 for (int i = 0; i < 8; i++) {
12209 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12210 if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12211 LOG("No SleepWake blob to read beyond chunk %d\n", i);
12212 break;
12213 }
12214 if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12215 PERemoveNVRAMProperty(nvram_var_name_buffer);
12216 LOG("Could not read the property :-(\n");
12217 break;
12218 }
12219 PERemoveNVRAMProperty(nvram_var_name_buffer);
12220 concat_len += len;
12221 }
12222 LOG("Concatenated length for the SWD blob %d\n", concat_len);
12223
12224 if (concat_len) {
12225 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12226 if (error) {
12227 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12228 } else {
12229 LOG("Saved SleepWake zipped data to file.\n");
12230 }
12231 } else {
12232 // There is a sleep wake failure string but no stackshot
12233 // Write a placeholder stacks file so that swd runs
12234 snprintf(outbuf, 20, "%s", "No stackshot data\n");
12235 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12236 if (error) {
12237 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12238 } else {
12239 LOG("Saved SleepWake zipped data to file.\n");
12240 }
12241 }
12242 } else {
12243 LOG("No buffer allocated to save failure stackshot\n");
12244 }
12245
12246
12247 gRootDomain->swd_lock = 0;
12248 exit:
12249 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12250 return;
12251 }
12252
12253
12254 void
12255 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12256 {
12257 OSSharedPtr<IORegistryIterator> iter;
12258 OSSharedPtr<const OSSymbol> kextName = NULL;
12259 IORegistryEntry * entry;
12260 IOService * node;
12261 bool nodeFound = false;
12262
12263 const void * callMethod = NULL;
12264 const char * objectName = NULL;
12265 const char * phaseString = NULL;
12266 const char * phaseDescription = NULL;
12267 uint64_t delta;
12268
12269 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12270 uint32_t tracePhase = pmTracer->getTracePhase();
12271
12272 *thread = NULL;
12273
12274 delta = get_watchdog_elapsed_time();
12275 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12276 snprintf(failureStr, strLen, "Sleep transition timed out after %qd seconds", delta);
12277 } else {
12278 snprintf(failureStr, strLen, "Wake transition timed out after %qd seconds", delta);
12279 }
12280 tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12281
12282 if (notifierThread) {
12283 if (notifier && (notifier->identifier)) {
12284 objectName = notifier->identifier->getCStringNoCopy();
12285 }
12286 *thread = notifierThread;
12287 } else {
12288 iter = IORegistryIterator::iterateOver(
12289 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12290
12291 if (iter) {
12292 while ((entry = iter->getNextObject())) {
12293 node = OSDynamicCast(IOService, entry);
12294 if (!node) {
12295 continue;
12296 }
12297 if (OSDynamicCast(IOPowerConnection, node)) {
12298 continue;
12299 }
12300
12301 if (node->getBlockingDriverCall(thread, &callMethod)) {
12302 nodeFound = true;
12303 break;
12304 }
12305 }
12306 }
12307 if (nodeFound) {
12308 kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12309 if (kextName) {
12310 objectName = kextName->getCStringNoCopy();
12311 }
12312 }
12313 }
12314 if (phaseDescription) {
12315 strlcat(failureStr, " while ", strLen);
12316 strlcat(failureStr, phaseDescription, strLen);
12317 strlcat(failureStr, ".", strLen);
12318 }
12319 if (objectName) {
12320 strlcat(failureStr, " Suspected bundle: ", strLen);
12321 strlcat(failureStr, objectName, strLen);
12322 strlcat(failureStr, ".", strLen);
12323 }
12324 if (*thread) {
12325 char threadName[40];
12326 snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12327 strlcat(failureStr, threadName, strLen);
12328 }
12329
12330 DLOG("%s\n", failureStr);
12331 }
12332
12333 struct swd_stackshot_compressed_data {
12334 z_output_func zoutput;
12335 size_t zipped;
12336 uint64_t totalbytes;
12337 uint64_t lastpercent;
12338 IOReturn error;
12339 unsigned outremain;
12340 unsigned outlen;
12341 unsigned writes;
12342 Bytef * outbuf;
12343 };
12344 struct swd_stackshot_compressed_data swd_zip_var = { };
12345
12346 static void *
12347 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12348 {
12349 void *result;
12350 LOG("Alloc in zipping %d items of size %d\n", items, size);
12351
12352 result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12353 swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12354 LOG("Offset %zu\n", swd_zs_zoffset);
12355 return result;
12356 }
12357
12358 static int
12359 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12360 {
12361 unsigned len;
12362
12363 len = strm->avail_in;
12364
12365 if (len > size) {
12366 len = size;
12367 }
12368 if (len == 0) {
12369 return 0;
12370 }
12371
12372 if (strm->next_in != (Bytef *) strm) {
12373 memcpy(buf, strm->next_in, len);
12374 } else {
12375 bzero(buf, len);
12376 }
12377
12378 strm->adler = z_crc32(strm->adler, buf, len);
12379
12380 strm->avail_in -= len;
12381 strm->next_in += len;
12382 strm->total_in += len;
12383
12384 return (int)len;
12385 }
12386
12387 static int
12388 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12389 {
12390 unsigned int i = 0;
12391 // if outlen > max size don't add to the buffer
12392 assert(buf != NULL);
12393 if (strm && buf) {
12394 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12395 LOG("No space to GZIP... not writing to NVRAM\n");
12396 return len;
12397 }
12398 }
12399 for (i = 0; i < len; i++) {
12400 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12401 }
12402 swd_zip_var.outlen += len;
12403 return len;
12404 }
12405
12406 static void
12407 swd_zs_free(void * __unused ref, void * __unused ptr)
12408 {
12409 }
12410
12411 static int
12412 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12413 {
12414 int wbits = 12;
12415 int memlevel = 3;
12416
12417 if (((unsigned int) numBytes) != numBytes) {
12418 return 0;
12419 }
12420
12421 if (!swd_zs.zalloc) {
12422 swd_zs.zalloc = swd_zs_alloc;
12423 swd_zs.zfree = swd_zs_free;
12424 if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12425 // allocation failed
12426 bzero(&swd_zs, sizeof(swd_zs));
12427 // swd_zs_zoffset = 0;
12428 } else {
12429 LOG("PMRD inited the zlib allocation routines\n");
12430 }
12431 }
12432
12433 swd_zip_var.zipped = 0;
12434 swd_zip_var.totalbytes = 0; // should this be the max that we have?
12435 swd_zip_var.lastpercent = 0;
12436 swd_zip_var.error = kIOReturnSuccess;
12437 swd_zip_var.outremain = 0;
12438 swd_zip_var.outlen = 0;
12439 swd_zip_var.writes = 0;
12440 swd_zip_var.outbuf = (Bytef *)outPtr;
12441
12442 swd_zip_var.totalbytes = numBytes;
12443
12444 swd_zs.avail_in = 0;
12445 swd_zs.next_in = NULL;
12446 swd_zs.avail_out = 0;
12447 swd_zs.next_out = NULL;
12448
12449 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12450
12451 z_stream *zs;
12452 int zr;
12453 zs = &swd_zs;
12454
12455 while (swd_zip_var.error >= 0) {
12456 if (!zs->avail_in) {
12457 zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12458 zs->avail_in = (unsigned int) numBytes;
12459 }
12460 if (!zs->avail_out) {
12461 zs->next_out = (Bytef *)zs;
12462 zs->avail_out = UINT32_MAX;
12463 }
12464 zr = deflate(zs, Z_NO_FLUSH);
12465 if (Z_STREAM_END == zr) {
12466 break;
12467 }
12468 if (zr != Z_OK) {
12469 LOG("ZERR %d\n", zr);
12470 swd_zip_var.error = zr;
12471 } else {
12472 if (zs->total_in == numBytes) {
12473 break;
12474 }
12475 }
12476 }
12477
12478 //now flush the stream
12479 while (swd_zip_var.error >= 0) {
12480 if (!zs->avail_out) {
12481 zs->next_out = (Bytef *)zs;
12482 zs->avail_out = UINT32_MAX;
12483 }
12484 zr = deflate(zs, Z_FINISH);
12485 if (Z_STREAM_END == zr) {
12486 break;
12487 }
12488 if (zr != Z_OK) {
12489 LOG("ZERR %d\n", zr);
12490 swd_zip_var.error = zr;
12491 } else {
12492 if (zs->total_in == numBytes) {
12493 LOG("Total output size %d\n", swd_zip_var.outlen);
12494 break;
12495 }
12496 }
12497 }
12498
12499 return swd_zip_var.outlen;
12500 }
12501
12502 void
12503 IOPMrootDomain::deleteStackshot()
12504 {
12505 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12506 // takeStackshot hasn't completed
12507 return;
12508 }
12509 LOG("Deleting any sleepwake failure data in nvram\n");
12510
12511 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12512 char nvram_var_name_buf[20];
12513 for (int i = 0; i < 8; i++) {
12514 snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12515 if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12516 LOG("Removing %s returned false\n", nvram_var_name_buf);
12517 }
12518 }
12519 // force NVRAM sync
12520 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12521 DLOG("Failed to force nvram sync\n");
12522 }
12523 gRootDomain->swd_lock = 0;
12524 }
12525
12526 void
12527 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12528 {
12529 swd_hdr * hdr = NULL;
12530 int cnt = 0;
12531 int max_cnt;
12532 pid_t pid = 0;
12533 kern_return_t kr = KERN_SUCCESS;
12534 uint64_t flags;
12535
12536 char * dstAddr;
12537 uint32_t size;
12538 uint32_t bytesRemaining;
12539 unsigned bytesWritten = 0;
12540
12541 char failureStr[512];
12542 thread_t thread = NULL;
12543 const char * swfPanic = "swfPanic";
12544
12545 uint32_t bufSize;
12546 int success = 0;
12547
12548 #if defined(__i386__) || defined(__x86_64__)
12549 const bool concise = false;
12550 #else
12551 const bool concise = true;
12552 #endif
12553
12554 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12555 return;
12556 }
12557
12558 failureStr[0] = 0;
12559 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12560 return;
12561 }
12562
12563 if (wdogTrigger) {
12564 getFailureData(&thread, failureStr, sizeof(failureStr));
12565
12566 if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12567 goto skip_stackshot;
12568 }
12569 } else {
12570 AbsoluteTime now;
12571 uint64_t nsec;
12572 clock_get_uptime(&now);
12573 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12574 absolutetime_to_nanoseconds(now, &nsec);
12575 snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12576 }
12577
12578 if (swd_buffer == NULL) {
12579 sleepWakeDebugMemAlloc();
12580 if (swd_buffer == NULL) {
12581 return;
12582 }
12583 }
12584 hdr = (swd_hdr *)swd_buffer;
12585 bufSize = hdr->alloc_size;
12586
12587 dstAddr = (char*)hdr + hdr->spindump_offset;
12588 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;
12589
12590 /* If not wdogTrigger only take kernel tasks stackshot
12591 */
12592 if (wdogTrigger) {
12593 pid = -1;
12594 max_cnt = 3;
12595 } else {
12596 pid = 0;
12597 max_cnt = 2;
12598 }
12599
12600 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12601 * If we run out of space, take stackshot with only kernel task
12602 */
12603 while (success == 0 && cnt < max_cnt) {
12604 bytesRemaining = bufSize - hdr->spindump_offset;
12605 cnt++;
12606 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12607
12608 size = bytesRemaining;
12609 kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12610 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12611 kr, pid, size, flags, bytesWritten);
12612 if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12613 if (pid == -1) {
12614 pid = 0;
12615 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12616 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12617 } else {
12618 LOG("Insufficient buffer size for only kernel task\n");
12619 break;
12620 }
12621 }
12622 if (kr == KERN_SUCCESS) {
12623 if (bytesWritten == 0) {
12624 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12625 continue;
12626 }
12627 bytesRemaining -= bytesWritten;
12628 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12629
12630 memset(hdr->reason, 0x20, sizeof(hdr->reason));
12631
12632 // Compress stackshot and save to NVRAM
12633 {
12634 char *outbuf = (char *)swd_compressed_buffer;
12635 int outlen = 0;
12636 int num_chunks = 0;
12637 int max_chunks = 0;
12638 int leftover = 0;
12639 char nvram_var_name_buffer[20];
12640
12641 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12642
12643 if (outlen) {
12644 max_chunks = outlen / (2096 - 200);
12645 leftover = outlen % (2096 - 200);
12646
12647 if (max_chunks < 8) {
12648 for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
12649 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12650 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
12651 LOG("Failed to update NVRAM %d\n", num_chunks);
12652 break;
12653 }
12654 }
12655 if (leftover) {
12656 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12657 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
12658 LOG("Failed to update NVRAM with leftovers\n");
12659 }
12660 }
12661 success = 1;
12662 LOG("Successfully saved stackshot to NVRAM\n");
12663 } else {
12664 if (pid == -1) {
12665 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12666 pid = 0;
12667 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12668 LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
12669 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12670 } else {
12671 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12672 break;
12673 }
12674 }
12675 }
12676 }
12677 }
12678 }
12679
12680 if (failureStr[0]) {
12681 // append sleep-wake failure code
12682 char traceCode[80];
12683 snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
12684 pmTracer->getTraceData(), pmTracer->getTracePhase());
12685 strlcat(failureStr, traceCode, sizeof(failureStr));
12686 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
12687 DLOG("Failed to write SleepWake failure string\n");
12688 }
12689 }
12690
12691 // force NVRAM sync
12692 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12693 DLOG("Failed to force nvram sync\n");
12694 }
12695
12696 skip_stackshot:
12697 if (wdogTrigger) {
12698 if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
12699 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
12700 // If current boot is due to this watch dog trigger restart in previous boot,
12701 // then don't trigger again until at least 1 successful sleep & wake.
12702 if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
12703 LOG("Shutting down due to repeated Sleep/Wake failures\n");
12704 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12705 PEHaltRestart(kPEHaltCPU);
12706 return;
12707 }
12708 }
12709 if (gSwdPanic == 0) {
12710 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12711 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12712 PEHaltRestart(kPERestartCPU);
12713 }
12714 }
12715 if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12716 DLOG("Failed to write SleepWake failure panic key\n");
12717 }
12718 #if defined(__x86_64__)
12719 if (thread) {
12720 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12721 } else
12722 #endif /* defined(__x86_64__) */
12723 {
12724 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12725 }
12726 } else {
12727 gRootDomain->swd_lock = 0;
12728 return;
12729 }
12730 }
12731
12732 void
12733 IOPMrootDomain::sleepWakeDebugMemAlloc()
12734 {
12735 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12736
12737 swd_hdr *hdr = NULL;
12738 void *bufPtr = NULL;
12739
12740 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12741
12742
12743 if (kIOSleepWakeWdogOff & gIOKitDebug) {
12744 return;
12745 }
12746
12747 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12748 return;
12749 }
12750
12751 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12752 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12753 size);
12754 if (memDesc == NULL) {
12755 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12756 goto exit;
12757 }
12758
12759 bufPtr = memDesc->getBytesNoCopy();
12760
12761 // Carve out memory for zlib routines
12762 swd_zs_zmem = (vm_offset_t)bufPtr;
12763 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12764
12765 // Carve out memory for compressed stackshots
12766 swd_compressed_buffer = bufPtr;
12767 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12768
12769 // Remaining is used for holding stackshot
12770 hdr = (swd_hdr *)bufPtr;
12771 memset(hdr, 0, sizeof(swd_hdr));
12772
12773 hdr->signature = SWD_HDR_SIGNATURE;
12774 hdr->alloc_size = SWD_STACKSHOT_SIZE;
12775
12776 hdr->spindump_offset = sizeof(swd_hdr);
12777 swd_buffer = (void *)hdr;
12778 swd_memDesc = os::move(memDesc);
12779 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
12780
12781 exit:
12782 gRootDomain->swd_lock = 0;
12783 }
12784
12785 void
12786 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12787 {
12788 #if UNUSED
12789 vm_size_t size = SWD_SPINDUMP_SIZE;
12790
12791 swd_hdr *hdr = NULL;
12792
12793 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12794
12795 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12796 return;
12797 }
12798
12799 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12800 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12801 SWD_SPINDUMP_SIZE);
12802
12803 if (memDesc == NULL) {
12804 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12805 goto exit;
12806 }
12807
12808
12809 hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12810 memset(hdr, 0, sizeof(swd_hdr));
12811
12812 hdr->signature = SWD_HDR_SIGNATURE;
12813 hdr->alloc_size = size;
12814
12815 hdr->spindump_offset = sizeof(swd_hdr);
12816 swd_spindump_buffer = (void *)hdr;
12817 swd_spindump_memDesc = os::move(memDesc);
12818
12819 exit:
12820 gRootDomain->swd_lock = 0;
12821 #endif /* UNUSED */
12822 }
12823
12824 void
12825 IOPMrootDomain::sleepWakeDebugEnableWdog()
12826 {
12827 }
12828
12829 bool
12830 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12831 {
12832 return !systemBooting && !systemShutdown && !gWillShutdown;
12833 }
12834
12835 void
12836 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12837 {
12838 swd_hdr *hdr = NULL;
12839 errno_t error = EIO;
12840
12841 if (swd_spindump_buffer && gSpinDumpBufferFull) {
12842 hdr = (swd_hdr *)swd_spindump_buffer;
12843
12844 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12845 (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12846
12847 if (error) {
12848 return;
12849 }
12850
12851 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12852 (char*)hdr + offsetof(swd_hdr, UUID),
12853 sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12854
12855 gSpinDumpBufferFull = false;
12856 }
12857 }
12858
12859 errno_t
12860 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12861 {
12862 struct vnode *vp = NULL;
12863 vfs_context_t ctx = vfs_context_create(vfs_context_current());
12864 kauth_cred_t cred = vfs_context_ucred(ctx);
12865 struct vnode_attr va;
12866 errno_t error = EIO;
12867
12868 if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
12869 S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
12870 LOG("Failed to open the file %s\n", name);
12871 swd_flags |= SWD_FILEOP_ERROR;
12872 goto exit;
12873 }
12874 VATTR_INIT(&va);
12875 VATTR_WANTED(&va, va_nlink);
12876 /* Don't dump to non-regular files or files with links. */
12877 if (vp->v_type != VREG ||
12878 vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
12879 LOG("Bailing as this is not a regular file\n");
12880 swd_flags |= SWD_FILEOP_ERROR;
12881 goto exit;
12882 }
12883 VATTR_INIT(&va);
12884 VATTR_SET(&va, va_data_size, 0);
12885 vnode_setattr(vp, &va, ctx);
12886
12887
12888 if (buf != NULL) {
12889 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12890 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12891 if (error != 0) {
12892 LOG("Failed to save sleep wake log. err 0x%x\n", error);
12893 swd_flags |= SWD_FILEOP_ERROR;
12894 } else {
12895 DLOG("Saved %d bytes to file %s\n", len, name);
12896 }
12897 }
12898
12899 exit:
12900 if (vp) {
12901 vnode_close(vp, FWRITE, ctx);
12902 }
12903 if (ctx) {
12904 vfs_context_rele(ctx);
12905 }
12906
12907 return error;
12908 }
12909
12910 #else /* defined(__i386__) || defined(__x86_64__) */
12911
12912 void
12913 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12914 {
12915 if (restart) {
12916 if (gSwdPanic == 0) {
12917 return;
12918 }
12919 panic("Sleep/Wake hang detected");
12920 return;
12921 }
12922 }
12923
12924 void
12925 IOPMrootDomain::takeStackshot(bool restart)
12926 {
12927 #pragma unused(restart)
12928 }
12929
12930 void
12931 IOPMrootDomain::deleteStackshot()
12932 {
12933 }
12934
12935 void
12936 IOPMrootDomain::sleepWakeDebugMemAlloc()
12937 {
12938 }
12939
12940 void
12941 IOPMrootDomain::saveFailureData2File()
12942 {
12943 }
12944
12945 void
12946 IOPMrootDomain::sleepWakeDebugEnableWdog()
12947 {
12948 }
12949
12950 bool
12951 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12952 {
12953 return false;
12954 }
12955
12956 void
12957 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12958 {
12959 }
12960
12961 errno_t
12962 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12963 {
12964 return 0;
12965 }
12966
12967 #endif /* defined(__i386__) || defined(__x86_64__) */
12968
12969