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 (_driverKitMatchingAssertionCount != 0) {
7523 err = kPMCPUAssertion;
7524 break;
7525 }
7526
7527 // Check for any dexts currently being added to the PM tree. Sleeping while
7528 // this is in flight can cause IOServicePH to timeout.
7529 if (!IOServicePH::checkPMReady()) {
7530 #if !defined(XNU_TARGET_OS_OSX)
7531 if (!(lowBatteryCondition || thermalWarningState || thermalEmergencyState)) {
7532 // 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
7533 // in dark wake for long periods of time, which causes issues as apps were
7534 // already informed of sleep during the f->9 transition. As a temporary
7535 // measure, always full wake if we hit this specific condition.
7536 pmPowerStateQueue->submitPowerEvent(
7537 kPowerEventPolicyStimulus,
7538 (void *) kStimulusDarkWakeActivityTickle);
7539 }
7540 #endif
7541 err = kPMDKNotReady;
7542 break;
7543 }
7544
7545 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7546 break; // always sleep on low battery or when in thermal warning/emergency state
7547 }
7548
7549 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7550 break; // always sleep on dark wake thermal emergencies
7551 }
7552
7553 if (preventSystemSleepList->getCount() != 0) {
7554 err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7555 break;
7556 }
7557
7558
7559 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7560 kIOPMDriverAssertionLevelOn) {
7561 err = kPMCPUAssertion; // 5. CPU assertion
7562 break;
7563 }
7564
7565 if (pciCantSleepValid) {
7566 if (pciCantSleepFlag) {
7567 err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7568 }
7569 break;
7570 } else if (sleepSupportedPEFunction &&
7571 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7572 IOReturn ret;
7573 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7574 ret = getPlatform()->callPlatformFunction(
7575 sleepSupportedPEFunction.get(), false,
7576 NULL, NULL, NULL, NULL);
7577 pciCantSleepValid = true;
7578 pciCantSleepFlag = false;
7579 if ((platformSleepSupport & kPCICantSleep) ||
7580 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7581 err = 6; // 6. PCI card does not support PM
7582 pciCantSleepFlag = true;
7583 break;
7584 }
7585 }
7586 }while (false);
7587
7588 if (err) {
7589 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7590 return false;
7591 }
7592 return true;
7593 }
7594
7595 bool
7596 IOPMrootDomain::checkSystemSleepEnabled( void )
7597 {
7598 return checkSystemSleepAllowed(0, 0);
7599 }
7600
7601 bool
7602 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7603 {
7604 ASSERT_GATED();
7605 return checkSystemSleepAllowed(1, sleepReason);
7606 }
7607
7608 //******************************************************************************
7609 // checkSystemCanSustainFullWake
7610 //******************************************************************************
7611
7612 bool
7613 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7614 {
7615 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7616 // Low battery wake, or received a low battery notification
7617 // while system is awake. This condition will persist until
7618 // the following wake.
7619 return false;
7620 }
7621
7622 if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7623 // Graphics state is unknown and external display might not be probed.
7624 // Do not incorporate state that requires graphics to be in max power
7625 // such as desktopMode or clamshellDisabled.
7626
7627 if (!acAdaptorConnected) {
7628 DLOG("full wake check: no AC\n");
7629 return false;
7630 }
7631 }
7632 return true;
7633 }
7634
7635 //******************************************************************************
7636 // checkSystemCanAbortIdleSleep
7637 //******************************************************************************
7638
7639 bool
7640 IOPMrootDomain::checkSystemCanAbortIdleSleep( void )
7641 {
7642 bool abortableSleepType = ((lastSleepReason == kIOPMSleepReasonIdle)
7643 || (lastSleepReason == 0));
7644 return idleSleepRevertible && abortableSleepType;
7645 }
7646
7647 //******************************************************************************
7648 // attemptIdleSleepAbort
7649 //******************************************************************************
7650
7651 bool
7652 IOPMrootDomain::attemptIdleSleepAbort( void )
7653 {
7654 if (!gIOPMWorkLoop->inGate()) {
7655 bool ret = gIOPMWorkLoop->runAction(
7656 OSMemberFunctionCast(IOWorkLoop::Action, this,
7657 &IOPMrootDomain::attemptIdleSleepAbort),
7658 this);
7659 return ret;
7660 }
7661
7662 bool canAbort = checkSystemCanAbortIdleSleep();
7663 if (canAbort) {
7664 cancelIdlePowerDownSync();
7665 } else if (lastSleepReason == kIOPMSleepReasonIdle) {
7666 scheduleImmediateDebugWake();
7667 }
7668
7669 return canAbort;
7670 }
7671
7672 //******************************************************************************
7673 // setIdleSleepRevertible
7674 //******************************************************************************
7675
7676 void
7677 IOPMrootDomain::setIdleSleepRevertible( bool revertible )
7678 {
7679 idleSleepRevertible = revertible;
7680 }
7681
7682 //******************************************************************************
7683 // mustHibernate
7684 //******************************************************************************
7685
7686 #if HIBERNATION
7687
7688 bool
7689 IOPMrootDomain::mustHibernate( void )
7690 {
7691 return lowBatteryCondition || thermalWarningState;
7692 }
7693
7694 #endif /* HIBERNATION */
7695
7696 //******************************************************************************
7697 // AOT
7698 //******************************************************************************
7699
7700 // Tables for accumulated days in year by month, latter used for leap years
7701
7702 static const unsigned int daysbymonth[] =
7703 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7704
7705 static const unsigned int lydaysbymonth[] =
7706 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7707
7708 static int __unused
7709 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7710 {
7711 const unsigned int * dbm = daysbymonth;
7712 clock_sec_t n, x, y, z;
7713
7714 // Calculate seconds, minutes and hours
7715
7716 n = secs % (24 * 3600);
7717 dt->second = n % 60;
7718 n /= 60;
7719 dt->minute = n % 60;
7720 dt->hour = (typeof(dt->hour))(n / 60);
7721
7722 // Calculate day of week
7723
7724 n = secs / (24 * 3600);
7725 // dt->dayWeek = (n + 4) % 7;
7726
7727 // Calculate year
7728 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7729 // to days since 1/1/1968 to start on 4 year cycle, beginning
7730 // on a leap year.
7731
7732 n += (366 + 365);
7733
7734 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7735 // Valid before 2100, since 2100 is not a leap year.
7736
7737 x = n / 1461; // number of 4 year cycles
7738 y = n % 1461; // days into current 4 year cycle
7739 z = 1968 + (4 * x);
7740
7741 // Add in years in the current 4 year cycle
7742
7743 if (y >= 366) {
7744 y -= 366; // days after the leap year
7745 n = y % 365; // days into the current year
7746 z += (1 + y / 365); // years after the past 4-yr cycle
7747 } else {
7748 n = y;
7749 dbm = lydaysbymonth;
7750 }
7751 if (z > 2099) {
7752 return 0;
7753 }
7754
7755 dt->year = (typeof(dt->year))z;
7756
7757 // Adjust remaining days value to start at 1
7758
7759 n += 1;
7760
7761 // Calculate month
7762
7763 for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7764 continue;
7765 }
7766 dt->month = (typeof(dt->month))x;
7767
7768 // Calculate day of month
7769
7770 dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7771
7772 return 1;
7773 }
7774
7775 static clock_sec_t
7776 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7777 {
7778 const unsigned int * dbm = daysbymonth;
7779 long y, secs, days;
7780
7781 if (dt->year < 1970 || dt->month > 12) {
7782 return 0;
7783 }
7784
7785 // Seconds elapsed in the current day
7786
7787 secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7788
7789 // Number of days from 1/1/70 to beginning of current year
7790 // Account for extra day every 4 years starting at 1973
7791
7792 y = dt->year - 1970;
7793 days = (y * 365) + ((y + 1) / 4);
7794
7795 // Change table if current year is a leap year
7796
7797 if ((dt->year % 4) == 0) {
7798 dbm = lydaysbymonth;
7799 }
7800
7801 // Add in days elapsed in the current year
7802
7803 days += (dt->day - 1) + dbm[dt->month - 1];
7804
7805 // Add accumulated days to accumulated seconds
7806
7807 secs += 24 * 3600 * days;
7808
7809 return secs;
7810 }
7811
7812 unsigned long
7813 IOPMrootDomain::getRUN_STATE(void)
7814 {
7815 return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
7816 }
7817
7818 bool
7819 IOPMrootDomain::isAOTMode()
7820 {
7821 return _aotNow;
7822 }
7823
7824 IOReturn
7825 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7826 {
7827 clock_sec_t nowsecs, wakesecs;
7828 clock_usec_t nowmicrosecs, wakemicrosecs;
7829 uint64_t nowAbs, wakeAbs;
7830
7831 if (!_aotMode) {
7832 return kIOReturnNotReady;
7833 }
7834
7835 clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
7836 wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
7837 if (wakeAbs < nowAbs) {
7838 printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
7839 wakeAbs = nowAbs;
7840 }
7841 wakeAbs -= nowAbs;
7842 absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7843
7844 wakesecs += nowsecs;
7845 wakemicrosecs += nowmicrosecs;
7846 if (wakemicrosecs >= USEC_PER_SEC) {
7847 wakesecs++;
7848 wakemicrosecs -= USEC_PER_SEC;
7849 }
7850 if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7851 wakesecs++;
7852 }
7853
7854 IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7855
7856 if (_aotWakeTimeContinuous != wakeContinuousTime) {
7857 _aotWakeTimeContinuous = wakeContinuousTime;
7858 IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7859 }
7860 _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7861 _aotWakeTimeUTC = wakesecs;
7862
7863 return kIOReturnSuccess;
7864 }
7865
7866 // assumes WAKEEVENT_LOCK
7867 bool
7868 IOPMrootDomain::aotShouldExit(bool software)
7869 {
7870 bool exitNow = false;
7871 const char * reason = "";
7872
7873 if (!_aotNow) {
7874 return false;
7875 }
7876
7877 if (software) {
7878 exitNow = true;
7879 _aotMetrics->softwareRequestCount++;
7880 reason = "software request";
7881 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7882 exitNow = true;
7883 reason = gWakeReasonString;
7884 } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7885 clock_sec_t sec;
7886 clock_usec_t usec;
7887 clock_get_calendar_microtime(&sec, &usec);
7888 if (_calendarWakeAlarmUTC <= sec) {
7889 exitNow = true;
7890 _aotMetrics->rtcAlarmsCount++;
7891 reason = "user alarm";
7892 }
7893 }
7894 if (exitNow) {
7895 _aotPendingFlags |= kIOPMWakeEventAOTExit;
7896 IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7897 reason,
7898 _aotMetrics->sleepCount,
7899 _aotMetrics->possibleCount,
7900 _aotMetrics->confirmedPossibleCount,
7901 _aotMetrics->rejectedPossibleCount,
7902 _aotMetrics->expiredPossibleCount,
7903 _aotMetrics->noTimeSetCount,
7904 _aotMetrics->rtcAlarmsCount);
7905 }
7906 return exitNow;
7907 }
7908
7909 void
7910 IOPMrootDomain::aotExit(bool cps)
7911 {
7912 uint32_t savedMessageMask;
7913
7914 ASSERT_GATED();
7915 _aotNow = false;
7916 _aotReadyToFullWake = false;
7917 if (_aotTimerScheduled) {
7918 _aotTimerES->cancelTimeout();
7919 _aotTimerScheduled = false;
7920 }
7921 updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
7922
7923 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7924 _aotLastWakeTime = 0;
7925 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7926 WAKEEVENT_LOCK();
7927 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7928 gWakeReasonString,
7929 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7930 WAKEEVENT_UNLOCK();
7931 }
7932
7933 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7934
7935 // Preserve the message mask since a system wake transition
7936 // may have already started and initialized the mask.
7937 savedMessageMask = _systemMessageClientMask;
7938 _systemMessageClientMask = kSystemMessageClientLegacyApp;
7939 tellClients(kIOMessageSystemWillPowerOn);
7940 _systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
7941
7942 if (cps) {
7943 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7944 }
7945 }
7946
7947 void
7948 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7949 {
7950 bool exitNow;
7951
7952 IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7953
7954 WAKEEVENT_LOCK();
7955 exitNow = aotShouldExit(false);
7956 if (timer != NULL) {
7957 _aotTimerScheduled = false;
7958 }
7959 WAKEEVENT_UNLOCK();
7960 if (exitNow) {
7961 aotExit(true);
7962 } else {
7963 #if 0
7964 if (_aotLingerTime) {
7965 uint64_t deadline;
7966 IOLog("aot linger before sleep\n");
7967 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7968 clock_delay_until(deadline);
7969 }
7970 #endif
7971 privateSleepSystem(kIOPMSleepReasonSoftware);
7972 }
7973 }
7974
7975 //******************************************************************************
7976 // adjustPowerState
7977 //
7978 // Conditions that affect our wake/sleep decision has changed.
7979 // If conditions dictate that the system must remain awake, clamp power
7980 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7981 // is TRUE, then remove the power clamp and allow the power state to drop
7982 // to SLEEP_STATE.
7983 //******************************************************************************
7984
7985 void
7986 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7987 {
7988 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7989 getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7990
7991 ASSERT_GATED();
7992
7993 if (_aotNow) {
7994 bool exitNow;
7995
7996 if (AOT_STATE != getPowerState()) {
7997 return;
7998 }
7999 WAKEEVENT_LOCK();
8000 exitNow = aotShouldExit(false);
8001 if (!exitNow
8002 && !_aotTimerScheduled
8003 && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
8004 _aotTimerScheduled = true;
8005 if (_aotLingerTime) {
8006 _aotTimerES->setTimeout(_aotLingerTime);
8007 } else {
8008 _aotTimerES->setTimeout(800, kMillisecondScale);
8009 }
8010 }
8011 WAKEEVENT_UNLOCK();
8012 if (exitNow) {
8013 aotExit(true);
8014 } else {
8015 _aotReadyToFullWake = true;
8016 if (!_aotTimerScheduled) {
8017 if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
8018 // Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
8019 // Doing so will result in the sleep being cancelled anyway,
8020 // but this check avoids unnecessary thrashing in the power state engine.
8021 return;
8022 }
8023 privateSleepSystem(kIOPMSleepReasonSoftware);
8024 }
8025 }
8026 return;
8027 }
8028
8029 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
8030 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
8031 } else if (sleepASAP) {
8032 changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
8033 }
8034 }
8035
8036 void
8037 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
8038 {
8039 if (powerOn) {
8040 if (!checkSystemCanSustainFullWake()) {
8041 DLOG("System cannot sustain full wake\n");
8042 return;
8043 }
8044
8045 // Force wrangler to max power state. If system is in dark wake
8046 // this alone won't raise the wrangler's power state.
8047 if (wrangler) {
8048 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
8049 }
8050
8051 // System in dark wake, always requesting full wake should
8052 // not have any bad side-effects, even if the request fails.
8053
8054 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8055 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
8056 requestFullWake( kFullWakeReasonDisplayOn );
8057 }
8058 } else {
8059 // Relenquish desire to power up display.
8060 // Must first transition to state 1 since wrangler doesn't
8061 // power off the displays at state 0. At state 0 the root
8062 // domain is removed from the wrangler's power client list.
8063 if (wrangler) {
8064 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
8065 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
8066 }
8067 }
8068 }
8069
8070 TUNABLE(bool, test_sleep_in_vm, "test_sleep_in_vm", false);
8071
8072 //******************************************************************************
8073 // dispatchPowerEvent
8074 //
8075 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
8076 //******************************************************************************
8077
8078 void
8079 IOPMrootDomain::dispatchPowerEvent(
8080 uint32_t event, void * arg0, uint64_t arg1 )
8081 {
8082 ASSERT_GATED();
8083
8084 switch (event) {
8085 case kPowerEventFeatureChanged:
8086 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8087 messageClients(kIOPMMessageFeatureChange, this);
8088 break;
8089
8090 case kPowerEventReceivedPowerNotification:
8091 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8092 handlePowerNotification((UInt32)(uintptr_t) arg0 );
8093 break;
8094
8095 case kPowerEventSystemBootCompleted:
8096 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8097 if (systemBooting) {
8098 systemBooting = false;
8099
8100 if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
8101 DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
8102 if (test_sleep_in_vm && gSleepDisabledFlag) {
8103 DLOG("Clearing gSleepDisabledFlag due to test_sleep_in_vm boot-arg\n");
8104 gSleepDisabledFlag = 0;
8105 }
8106 }
8107
8108 if (lowBatteryCondition || thermalEmergencyState) {
8109 if (lowBatteryCondition) {
8110 privateSleepSystem(kIOPMSleepReasonLowPower);
8111 } else {
8112 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8113 }
8114 // The rest is unnecessary since the system is expected
8115 // to sleep immediately. The following wake will update
8116 // everything.
8117 break;
8118 }
8119
8120 sleepWakeDebugMemAlloc();
8121 saveFailureData2File();
8122
8123 // If lid is closed, re-send lid closed notification
8124 // now that booting is complete.
8125 if (clamshellClosed) {
8126 handlePowerNotification(kLocalEvalClamshellCommand);
8127 }
8128 evaluatePolicy( kStimulusAllowSystemSleepChanged );
8129 }
8130 break;
8131
8132 case kPowerEventSystemShutdown:
8133 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8134 if (kOSBooleanTrue == (OSBoolean *) arg0) {
8135 /* We set systemShutdown = true during shutdown
8136 * to prevent sleep at unexpected times while loginwindow is trying
8137 * to shutdown apps and while the OS is trying to transition to
8138 * complete power of.
8139 *
8140 * Set to true during shutdown, as soon as loginwindow shows
8141 * the "shutdown countdown dialog", through individual app
8142 * termination, and through black screen kernel shutdown.
8143 */
8144 systemShutdown = true;
8145 } else {
8146 /*
8147 * A shutdown was initiated, but then the shutdown
8148 * was cancelled, clearing systemShutdown to false here.
8149 */
8150 systemShutdown = false;
8151 }
8152 break;
8153
8154 case kPowerEventUserDisabledSleep:
8155 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8156 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8157 break;
8158
8159 case kPowerEventRegisterSystemCapabilityClient:
8160 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8161
8162 // reset() handles the arg0 == nullptr case for us
8163 systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8164 /* intentional fall-through */
8165 [[clang::fallthrough]];
8166
8167 case kPowerEventRegisterKernelCapabilityClient:
8168 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8169 if (!_joinedCapabilityClients) {
8170 _joinedCapabilityClients = OSSet::withCapacity(8);
8171 }
8172 if (arg0) {
8173 OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8174 if (_joinedCapabilityClients) {
8175 _joinedCapabilityClients->setObject(notify.get());
8176 synchronizePowerTree( kIOPMSyncNoChildNotify );
8177 }
8178 }
8179 break;
8180
8181 case kPowerEventPolicyStimulus:
8182 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8183 if (arg0) {
8184 int stimulus = (int)(uintptr_t) arg0;
8185 evaluatePolicy(stimulus, (uint32_t) arg1);
8186 }
8187 break;
8188
8189 case kPowerEventAssertionCreate:
8190 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8191 if (pmAssertions) {
8192 pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8193 }
8194 break;
8195
8196
8197 case kPowerEventAssertionRelease:
8198 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8199 if (pmAssertions) {
8200 pmAssertions->handleReleaseAssertion(arg1);
8201 }
8202 break;
8203
8204 case kPowerEventAssertionSetLevel:
8205 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8206 if (pmAssertions) {
8207 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8208 }
8209 break;
8210
8211 case kPowerEventQueueSleepWakeUUID:
8212 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8213 handleQueueSleepWakeUUID((OSObject *)arg0);
8214 break;
8215 case kPowerEventPublishSleepWakeUUID:
8216 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8217 handlePublishSleepWakeUUID((bool)arg0);
8218 break;
8219
8220 case kPowerEventSetDisplayPowerOn:
8221 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8222 if (arg1 != 0) {
8223 displayPowerOnRequested = true;
8224 } else {
8225 displayPowerOnRequested = false;
8226 }
8227 handleSetDisplayPowerOn(displayPowerOnRequested);
8228 break;
8229
8230 case kPowerEventPublishWakeType:
8231 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8232
8233 // Don't replace wake type property if already set
8234 if ((arg0 == gIOPMWakeTypeUserKey) ||
8235 !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8236 const char * wakeType = NULL;
8237
8238 if (arg0 == gIOPMWakeTypeUserKey) {
8239 requestUserActive(this, "WakeTypeUser");
8240 wakeType = kIOPMRootDomainWakeTypeUser;
8241 } else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8242 if (!(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
8243 requestUserActive(this, "WakeTypeAlarm");
8244 }
8245 wakeType = kIOPMRootDomainWakeTypeAlarm;
8246 } else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8247 darkWakeSleepService = true;
8248 wakeType = kIOPMRootDomainWakeTypeSleepService;
8249 } else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8250 wakeType = kIOPMRootDomainWakeTypeMaintenance;
8251 }
8252
8253 if (wakeType) {
8254 setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8255 }
8256 }
8257 break;
8258
8259 case kPowerEventAOTEvaluate:
8260 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8261 if (_aotReadyToFullWake) {
8262 aotEvaluate(NULL);
8263 }
8264 break;
8265 }
8266 }
8267
8268 //******************************************************************************
8269 // systemPowerEventOccurred
8270 //
8271 // The power controller is notifying us of a hardware-related power management
8272 // event that we must handle.
8273 //
8274 // systemPowerEventOccurred covers the same functionality that
8275 // receivePowerNotification does; it simply provides a richer API for conveying
8276 // more information.
8277 //******************************************************************************
8278
8279 IOReturn
8280 IOPMrootDomain::systemPowerEventOccurred(
8281 const OSSymbol *event,
8282 uint32_t intValue)
8283 {
8284 IOReturn attempt = kIOReturnSuccess;
8285 OSSharedPtr<OSNumber> newNumber;
8286
8287 if (!event) {
8288 return kIOReturnBadArgument;
8289 }
8290
8291 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8292 if (!newNumber) {
8293 return kIOReturnInternalError;
8294 }
8295
8296 attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8297
8298 return attempt;
8299 }
8300
8301 void
8302 IOPMrootDomain::setThermalState(OSObject *value)
8303 {
8304 OSNumber * num;
8305
8306 if (gIOPMWorkLoop->inGate() == false) {
8307 gIOPMWorkLoop->runAction(
8308 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8309 (OSObject *)this,
8310 (void *)value);
8311
8312 return;
8313 }
8314 if (value && (num = OSDynamicCast(OSNumber, value))) {
8315 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8316 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8317 }
8318 }
8319
8320 IOReturn
8321 IOPMrootDomain::systemPowerEventOccurred(
8322 const OSSymbol *event,
8323 OSObject *value)
8324 {
8325 OSSharedPtr<OSDictionary> thermalsDict;
8326 bool shouldUpdate = true;
8327
8328 if (!event || !value) {
8329 return kIOReturnBadArgument;
8330 }
8331
8332 // LOCK
8333 // We reuse featuresDict Lock because it already exists and guards
8334 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
8335 // of stepping on that lock.
8336 if (featuresDictLock) {
8337 IOLockLock(featuresDictLock);
8338 }
8339
8340 OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8341 OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8342
8343 if (origThermalsDict) {
8344 thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8345 } else {
8346 thermalsDict = OSDictionary::withCapacity(1);
8347 }
8348
8349 if (!thermalsDict) {
8350 shouldUpdate = false;
8351 goto exit;
8352 }
8353
8354 thermalsDict->setObject(event, value);
8355
8356 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8357
8358 exit:
8359 // UNLOCK
8360 if (featuresDictLock) {
8361 IOLockUnlock(featuresDictLock);
8362 }
8363
8364 if (shouldUpdate) {
8365 if (event &&
8366 event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8367 setThermalState(value);
8368 }
8369 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8370 }
8371
8372 return kIOReturnSuccess;
8373 }
8374
8375 //******************************************************************************
8376 // receivePowerNotification
8377 //
8378 // The power controller is notifying us of a hardware-related power management
8379 // event that we must handle. This may be a result of an 'environment' interrupt
8380 // from the power mgt micro.
8381 //******************************************************************************
8382
8383 IOReturn
8384 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8385 {
8386 if (msg & kIOPMPowerButton) {
8387 uint32_t currentPhase = pmTracer->getTracePhase();
8388 if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8389 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8390 swd_flags |= SWD_PWR_BTN_STACKSHOT;
8391 thread_call_enter(powerButtonDown);
8392 } else {
8393 DEBUG_LOG("power button pressed when system is up\n");
8394 }
8395 } else if (msg & kIOPMPowerButtonUp) {
8396 if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8397 swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8398 thread_call_enter(powerButtonUp);
8399 }
8400 } else {
8401 pmPowerStateQueue->submitPowerEvent(
8402 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8403 }
8404 return kIOReturnSuccess;
8405 }
8406
8407 void
8408 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8409 {
8410 bool eval_clamshell = false;
8411 bool eval_clamshell_alarm = false;
8412
8413 ASSERT_GATED();
8414
8415 /*
8416 * Local (IOPMrootDomain only) eval clamshell command
8417 */
8418 if (msg & kLocalEvalClamshellCommand) {
8419 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8420 eval_clamshell_alarm = true;
8421
8422 // reset isRTCAlarmWake. This evaluation should happen only once
8423 // on RTC/Alarm wake. Any clamshell events after wake should follow
8424 // the regular evaluation
8425 isRTCAlarmWake = false;
8426 } else {
8427 eval_clamshell = true;
8428 }
8429 }
8430
8431 /*
8432 * Overtemp
8433 */
8434 if (msg & kIOPMOverTemp) {
8435 DLOG("Thermal overtemp message received!\n");
8436 thermalEmergencyState = true;
8437 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8438 }
8439
8440 /*
8441 * Forward DW thermal notification to client, if system is not going to sleep
8442 */
8443 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8444 DLOG("DarkWake thermal limits message received!\n");
8445 messageClients(kIOPMMessageDarkWakeThermalEmergency);
8446 }
8447
8448 /*
8449 * Sleep Now!
8450 */
8451 if (msg & kIOPMSleepNow) {
8452 privateSleepSystem(kIOPMSleepReasonSoftware);
8453 }
8454
8455 /*
8456 * Power Emergency
8457 */
8458 if (msg & kIOPMPowerEmergency) {
8459 DLOG("Received kIOPMPowerEmergency");
8460 #if HIBERNATION && defined(__arm64__)
8461 if (!ml_is_secure_hib_supported()) {
8462 // Wait for the next low battery notification if the system state is
8463 // in transition.
8464 if ((_systemTransitionType == kSystemTransitionNone) &&
8465 CAP_CURRENT(kIOPMSystemCapabilityCPU) &&
8466 !systemBooting && !systemShutdown && !gWillShutdown) {
8467 // Setting lowBatteryCondition will prevent system sleep
8468 lowBatteryCondition = true;
8469
8470 // Notify userspace to initiate system shutdown
8471 messageClients(kIOPMMessageRequestSystemShutdown);
8472 }
8473 } else {
8474 lowBatteryCondition = true;
8475 privateSleepSystem(kIOPMSleepReasonLowPower);
8476 }
8477 #else /* HIBERNATION && defined(__arm64__) */
8478 lowBatteryCondition = true;
8479 privateSleepSystem(kIOPMSleepReasonLowPower);
8480 #endif /* HIBERNATION && defined(__arm64__) */
8481 }
8482
8483 /*
8484 * Clamshell OPEN
8485 */
8486 if (msg & kIOPMClamshellOpened) {
8487 DLOG("Clamshell opened\n");
8488 // Received clamshel open message from clamshell controlling driver
8489 // Update our internal state and tell general interest clients
8490 clamshellClosed = false;
8491 clamshellExists = true;
8492
8493 // Don't issue a hid tickle when lid is open and polled on wake
8494 if (msg & kIOPMSetValue) {
8495 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8496 reportUserInput();
8497 }
8498
8499 // Tell PMCPU
8500 informCPUStateChange(kInformLid, 0);
8501
8502 // Tell general interest clients
8503 sendClientClamshellNotification();
8504
8505 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
8506 || (lastSleepReason == kIOPMSleepReasonIdle)
8507 || (lastSleepReason == kIOPMSleepReasonMaintenance));
8508 if (aborting) {
8509 userActivityCount++;
8510 }
8511 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8512 }
8513
8514 /*
8515 * Clamshell CLOSED
8516 * Send the clamshell interest notification since the lid is closing.
8517 */
8518 if (msg & kIOPMClamshellClosed) {
8519 if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8520 clamshellClosed && clamshellExists) {
8521 DLOG("Ignoring redundant Clamshell close event\n");
8522 } else {
8523 DLOG("Clamshell closed\n");
8524 // Received clamshel open message from clamshell controlling driver
8525 // Update our internal state and tell general interest clients
8526 clamshellClosed = true;
8527 clamshellExists = true;
8528
8529 // Ignore all following clamshell close events until the clamshell
8530 // is opened or the system sleeps. When a clamshell close triggers
8531 // a system wake, the lid driver may send us two clamshell close
8532 // events, one for the clamshell close event itself, and a second
8533 // close event when the driver polls the lid state on wake.
8534 clamshellIgnoreClose = true;
8535
8536 // Tell PMCPU
8537 informCPUStateChange(kInformLid, 1);
8538
8539 // Tell general interest clients
8540 sendClientClamshellNotification();
8541
8542 // And set eval_clamshell = so we can attempt
8543 eval_clamshell = true;
8544 }
8545 }
8546
8547 /*
8548 * Set Desktop mode (sent from graphics)
8549 *
8550 * -> reevaluate lid state
8551 */
8552 if (msg & kIOPMSetDesktopMode) {
8553 desktopMode = (0 != (msg & kIOPMSetValue));
8554 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8555 DLOG("Desktop mode %d\n", desktopMode);
8556
8557 sendClientClamshellNotification();
8558
8559 // Re-evaluate the lid state
8560 eval_clamshell = true;
8561 }
8562
8563 /*
8564 * AC Adaptor connected
8565 *
8566 * -> reevaluate lid state
8567 */
8568 if (msg & kIOPMSetACAdaptorConnected) {
8569 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8570 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8571
8572 // Tell CPU PM
8573 informCPUStateChange(kInformAC, !acAdaptorConnected);
8574
8575 // Tell BSD if AC is connected
8576 // 0 == external power source; 1 == on battery
8577 post_sys_powersource(acAdaptorConnected ? 0:1);
8578
8579 sendClientClamshellNotification();
8580
8581 IOUserServer::powerSourceChanged(acAdaptorConnected);
8582
8583 // Re-evaluate the lid state
8584 eval_clamshell = true;
8585
8586 // Lack of AC may have latched a display wrangler tickle.
8587 // This mirrors the hardware's USB wake event latch, where a latched
8588 // USB wake event followed by an AC attach will trigger a full wake.
8589 latchDisplayWranglerTickle( false );
8590
8591 #if HIBERNATION
8592 // AC presence will reset the standy timer delay adjustment.
8593 _standbyTimerResetSeconds = 0;
8594 #endif
8595 if (!userIsActive) {
8596 // Reset userActivityTime when power supply is changed(rdr 13789330)
8597 clock_get_uptime(&userActivityTime);
8598 }
8599 }
8600
8601 /*
8602 * Enable Clamshell (external display disappear)
8603 *
8604 * -> reevaluate lid state
8605 */
8606 if (msg & kIOPMEnableClamshell) {
8607 DLOG("Clamshell enabled\n");
8608
8609 // Re-evaluate the lid state
8610 // System should sleep on external display disappearance
8611 // in lid closed operation.
8612 if (true == clamshellDisabled) {
8613 eval_clamshell = true;
8614
8615 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8616 // Also clear kClamshellSleepDisableInternal when graphics enables
8617 // the clamshell during a full wake. When graphics is behaving as
8618 // expected, this will allow clamshell close to be honored earlier
8619 // rather than waiting for the delayed evaluation.
8620 if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8621 (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8622 CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8623 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8624
8625 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8626 // when timer expires which is harmless but useless.
8627 thread_call_cancel(fullWakeThreadCall);
8628 }
8629 #endif
8630 }
8631
8632 clamshellDisabled = false;
8633 sendClientClamshellNotification();
8634 }
8635
8636 /*
8637 * Disable Clamshell (external display appeared)
8638 * We don't bother re-evaluating clamshell state. If the system is awake,
8639 * the lid is probably open.
8640 */
8641 if (msg & kIOPMDisableClamshell) {
8642 DLOG("Clamshell disabled\n");
8643 clamshellDisabled = true;
8644 sendClientClamshellNotification();
8645 }
8646
8647 /*
8648 * Evaluate clamshell and SLEEP if appropriate
8649 */
8650 if (eval_clamshell_alarm && clamshellClosed) {
8651 if (shouldSleepOnRTCAlarmWake()) {
8652 privateSleepSystem(kIOPMSleepReasonClamshell);
8653 }
8654 } else if (eval_clamshell && clamshellClosed) {
8655 if (shouldSleepOnClamshellClosed()) {
8656 privateSleepSystem(kIOPMSleepReasonClamshell);
8657 } else {
8658 evaluatePolicy( kStimulusDarkWakeEvaluate );
8659 }
8660 }
8661
8662 if (msg & kIOPMProModeEngaged) {
8663 int newState = 1;
8664 DLOG("ProModeEngaged\n");
8665 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8666 }
8667
8668 if (msg & kIOPMProModeDisengaged) {
8669 int newState = 0;
8670 DLOG("ProModeDisengaged\n");
8671 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8672 }
8673 }
8674
8675 //******************************************************************************
8676 // evaluatePolicy
8677 //
8678 // Evaluate root-domain policy in response to external changes.
8679 //******************************************************************************
8680
8681 void
8682 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8683 {
8684 union {
8685 struct {
8686 int idleSleepEnabled : 1;
8687 int idleSleepDisabled : 1;
8688 int displaySleep : 1;
8689 int sleepDelayChanged : 1;
8690 int evaluateDarkWake : 1;
8691 int adjustPowerState : 1;
8692 int userBecameInactive : 1;
8693 int displaySleepEntry : 1;
8694 } bit;
8695 uint32_t u32;
8696 } flags;
8697
8698
8699 ASSERT_GATED();
8700 flags.u32 = 0;
8701
8702 switch (stimulus) {
8703 case kStimulusDisplayWranglerSleep:
8704 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8705 if (!wranglerPowerOff) {
8706 // wrangler is in sleep state or lower
8707 flags.bit.displaySleep = true;
8708 }
8709 if (!wranglerAsleep) {
8710 // transition from wrangler wake to wrangler sleep
8711 flags.bit.displaySleepEntry = true;
8712 wranglerAsleep = true;
8713 }
8714 break;
8715
8716 case kStimulusDisplayWranglerWake:
8717 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8718 displayIdleForDemandSleep = false;
8719 wranglerPowerOff = false;
8720 wranglerAsleep = false;
8721 break;
8722
8723 case kStimulusEnterUserActiveState:
8724 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8725 if (_preventUserActive) {
8726 DLOG("user active dropped\n");
8727 break;
8728 }
8729 if (!userIsActive) {
8730 userIsActive = true;
8731 userWasActive = true;
8732 clock_get_uptime(&gUserActiveAbsTime);
8733
8734 // Stay awake after dropping demand for display power on
8735 if (kFullWakeReasonDisplayOn == fullWakeReason) {
8736 fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8737 DLOG("User activity while in notification wake\n");
8738 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8739 }
8740
8741 kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8742 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8743 messageClients(kIOPMMessageUserIsActiveChanged);
8744 }
8745 flags.bit.idleSleepDisabled = true;
8746 break;
8747
8748 case kStimulusLeaveUserActiveState:
8749 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8750 if (userIsActive) {
8751 clock_get_uptime(&gUserInactiveAbsTime);
8752 userIsActive = false;
8753 clock_get_uptime(&userBecameInactiveTime);
8754 flags.bit.userBecameInactive = true;
8755
8756 kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8757 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8758 messageClients(kIOPMMessageUserIsActiveChanged);
8759 }
8760 break;
8761
8762 case kStimulusAggressivenessChanged:
8763 {
8764 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8765 unsigned long aggressiveValue;
8766 uint32_t minutesToIdleSleep = 0;
8767 uint32_t minutesToDisplayDim = 0;
8768 uint32_t minutesDelta = 0;
8769
8770 // Fetch latest display and system sleep slider values.
8771 aggressiveValue = 0;
8772 getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8773 minutesToIdleSleep = (uint32_t) aggressiveValue;
8774
8775 aggressiveValue = 0;
8776 getAggressiveness(kPMMinutesToDim, &aggressiveValue);
8777 minutesToDisplayDim = (uint32_t) aggressiveValue;
8778 DLOG("aggressiveness changed: system %u->%u, display %u\n",
8779 sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
8780
8781 DLOG("idle time -> %d ms (ena %d)\n",
8782 idleMilliSeconds, (minutesToIdleSleep != 0));
8783
8784 // How long to wait before sleeping the system once
8785 // the displays turns off is indicated by 'extraSleepDelay'.
8786
8787 if (minutesToIdleSleep > minutesToDisplayDim) {
8788 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8789 } else if (minutesToIdleSleep == minutesToDisplayDim) {
8790 minutesDelta = 1;
8791 }
8792
8793 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8794 idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8795 }
8796
8797 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8798 flags.bit.idleSleepDisabled = true;
8799 idleSleepEnabled = false;
8800 }
8801 #if !defined(XNU_TARGET_OS_OSX)
8802 if (0x7fffffff == minutesToIdleSleep) {
8803 minutesToIdleSleep = idleMilliSeconds / 1000;
8804 }
8805 #endif /* !defined(XNU_TARGET_OS_OSX) */
8806
8807 if (((minutesDelta != extraSleepDelay) ||
8808 (userActivityTime != userActivityTime_prev)) &&
8809 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8810 flags.bit.sleepDelayChanged = true;
8811 }
8812
8813 if (systemDarkWake && !darkWakeToSleepASAP &&
8814 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8815 // Reconsider decision to remain in dark wake
8816 flags.bit.evaluateDarkWake = true;
8817 }
8818
8819 sleepSlider = minutesToIdleSleep;
8820 extraSleepDelay = minutesDelta;
8821 userActivityTime_prev = userActivityTime;
8822 } break;
8823
8824 case kStimulusDemandSystemSleep:
8825 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8826 displayIdleForDemandSleep = true;
8827 if (wrangler && wranglerIdleSettings) {
8828 // Request wrangler idle only when demand sleep is triggered
8829 // from full wake.
8830 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8831 wrangler->setProperties(wranglerIdleSettings.get());
8832 DLOG("Requested wrangler idle\n");
8833 }
8834 }
8835 // arg = sleepReason
8836 changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8837 break;
8838
8839 case kStimulusAllowSystemSleepChanged:
8840 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8841 flags.bit.adjustPowerState = true;
8842 break;
8843
8844 case kStimulusDarkWakeActivityTickle:
8845 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8846 // arg == true implies real and not self generated wrangler tickle.
8847 // Update wake type on PM work loop instead of the tickle thread to
8848 // eliminate the possibility of an early tickle clobbering the wake
8849 // type set by the platform driver.
8850 if (arg == true) {
8851 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8852 }
8853
8854 if (!darkWakeExit) {
8855 if (latchDisplayWranglerTickle(true)) {
8856 DLOG("latched tickle\n");
8857 break;
8858 }
8859
8860 darkWakeExit = true;
8861 DLOG("Requesting full wake due to dark wake activity tickle\n");
8862 requestFullWake( kFullWakeReasonLocalUser );
8863 }
8864 break;
8865
8866 case kStimulusDarkWakeEntry:
8867 case kStimulusDarkWakeReentry:
8868 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8869 // Any system transitions since the last dark wake transition
8870 // will invalid the stimulus.
8871
8872 if (arg == _systemStateGeneration) {
8873 DLOG("dark wake entry\n");
8874 systemDarkWake = true;
8875
8876 // Keep wranglerPowerOff an invariant when wrangler is absent
8877 if (wrangler) {
8878 wranglerPowerOff = true;
8879 }
8880
8881 if (kStimulusDarkWakeEntry == stimulus) {
8882 clock_get_uptime(&userBecameInactiveTime);
8883 flags.bit.evaluateDarkWake = true;
8884 if (activitySinceSleep()) {
8885 DLOG("User activity recorded while going to darkwake\n");
8886 reportUserInput();
8887 }
8888 }
8889
8890 // Always accelerate disk spindown while in dark wake,
8891 // even if system does not support/allow sleep.
8892
8893 cancelIdleSleepTimer();
8894 setQuickSpinDownTimeout();
8895 }
8896 break;
8897
8898 case kStimulusDarkWakeEvaluate:
8899 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8900 if (systemDarkWake) {
8901 flags.bit.evaluateDarkWake = true;
8902 }
8903 break;
8904
8905 case kStimulusNoIdleSleepPreventers:
8906 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8907 flags.bit.adjustPowerState = true;
8908 break;
8909 } /* switch(stimulus) */
8910
8911 if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
8912 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8913 darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
8914 if (darkWakeToSleepASAP ||
8915 (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
8916 uint32_t newSleepReason;
8917
8918 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8919 // System was previously in full wake. Sleep reason from
8920 // full to dark already recorded in fullToDarkReason.
8921
8922 if (lowBatteryCondition) {
8923 newSleepReason = kIOPMSleepReasonLowPower;
8924 } else if (thermalEmergencyState) {
8925 newSleepReason = kIOPMSleepReasonThermalEmergency;
8926 } else {
8927 newSleepReason = fullToDarkReason;
8928 }
8929 } else {
8930 // In dark wake from system sleep.
8931
8932 if (darkWakeSleepService) {
8933 newSleepReason = kIOPMSleepReasonSleepServiceExit;
8934 } else {
8935 newSleepReason = kIOPMSleepReasonMaintenance;
8936 }
8937 }
8938
8939 if (checkSystemCanSleep(newSleepReason)) {
8940 privateSleepSystem(newSleepReason);
8941 }
8942 } else { // non-maintenance (network) dark wake
8943 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8944 // Release power clamp, and wait for children idle.
8945 adjustPowerState(true);
8946 } else {
8947 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8948 }
8949 }
8950 }
8951
8952 if (systemDarkWake) {
8953 // The rest are irrelevant while system is in dark wake.
8954 flags.u32 = 0;
8955 }
8956
8957 if ((flags.bit.displaySleepEntry) &&
8958 (kFullWakeReasonDisplayOn == fullWakeReason)) {
8959 // kIOPMSleepReasonNotificationWakeExit
8960 DLOG("Display sleep while in notification wake\n");
8961 changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8962 }
8963
8964 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8965 bool cancelQuickSpindown = false;
8966
8967 if (flags.bit.sleepDelayChanged) {
8968 // Cancel existing idle sleep timer and quick disk spindown.
8969 // New settings will be applied by the idleSleepEnabled flag
8970 // handler below if idle sleep is enabled.
8971
8972 DLOG("extra sleep timer changed\n");
8973 cancelIdleSleepTimer();
8974 cancelQuickSpindown = true;
8975 } else {
8976 DLOG("user inactive\n");
8977 }
8978
8979 if (!userIsActive && idleSleepEnabled) {
8980 startIdleSleepTimer(getTimeToIdleSleep());
8981 }
8982
8983 if (cancelQuickSpindown) {
8984 restoreUserSpinDownTimeout();
8985 }
8986 }
8987
8988 if (flags.bit.idleSleepEnabled) {
8989 DLOG("idle sleep timer enabled\n");
8990 if (!wrangler) {
8991 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8992 startIdleSleepTimer(getTimeToIdleSleep());
8993 #else
8994 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8995 startIdleSleepTimer( idleMilliSeconds );
8996 #endif
8997 } else {
8998 // Start idle timer if prefs now allow system sleep
8999 // and user is already inactive. Disk spindown is
9000 // accelerated upon timer expiration.
9001
9002 if (!userIsActive) {
9003 startIdleSleepTimer(getTimeToIdleSleep());
9004 }
9005 }
9006 }
9007
9008 if (flags.bit.idleSleepDisabled) {
9009 DLOG("idle sleep timer disabled\n");
9010 cancelIdleSleepTimer();
9011 restoreUserSpinDownTimeout();
9012 adjustPowerState();
9013 }
9014
9015 if (flags.bit.adjustPowerState) {
9016 bool sleepASAP = false;
9017
9018 if (!systemBooting && (0 == idleSleepPreventersCount())) {
9019 if (!wrangler) {
9020 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
9021 if (idleSleepEnabled) {
9022 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
9023 if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
9024 sleepASAP = true;
9025 }
9026 #else
9027 // stay awake for at least idleMilliSeconds
9028 startIdleSleepTimer(idleMilliSeconds);
9029 #endif
9030 }
9031 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
9032 sleepASAP = true;
9033 }
9034 }
9035
9036 adjustPowerState(sleepASAP);
9037 }
9038 }
9039
9040 //******************************************************************************
9041
9042 unsigned int
9043 IOPMrootDomain::idleSleepPreventersCount()
9044 {
9045 if (_aotMode) {
9046 unsigned int count __block;
9047 count = 0;
9048 preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
9049 {
9050 count += (NULL == obj->metaCast("AppleARMBacklight"));
9051 return false;
9052 });
9053 return count;
9054 }
9055
9056 return preventIdleSleepList->getCount();
9057 }
9058
9059
9060 //******************************************************************************
9061 // requestFullWake
9062 //
9063 // Request transition from dark wake to full wake
9064 //******************************************************************************
9065
9066 void
9067 IOPMrootDomain::requestFullWake( FullWakeReason reason )
9068 {
9069 uint32_t options = 0;
9070 IOService * pciRoot = NULL;
9071 bool promotion = false;
9072
9073 // System must be in dark wake and a valid reason for entering full wake
9074 if ((kFullWakeReasonNone == reason) ||
9075 (kFullWakeReasonNone != fullWakeReason) ||
9076 (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
9077 return;
9078 }
9079
9080 // Will clear reason upon exit from full wake
9081 fullWakeReason = reason;
9082
9083 _desiredCapability |= (kIOPMSystemCapabilityGraphics |
9084 kIOPMSystemCapabilityAudio);
9085
9086 if ((kSystemTransitionWake == _systemTransitionType) &&
9087 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
9088 !darkWakePowerClamped) {
9089 // Promote to full wake while waking up to dark wake due to tickle.
9090 // PM will hold off notifying the graphics subsystem about system wake
9091 // as late as possible, so if a HID tickle does arrive, graphics can
9092 // power up from this same wake transition. Otherwise, the latency to
9093 // power up graphics on the following transition can be huge on certain
9094 // systems. However, once any power clamping has taken effect, it is
9095 // too late to promote the current dark wake transition to a full wake.
9096 _pendingCapability |= (kIOPMSystemCapabilityGraphics |
9097 kIOPMSystemCapabilityAudio);
9098
9099 // Tell the PCI parent of audio and graphics drivers to stop
9100 // delaying the child notifications. Same for root domain.
9101 pciRoot = pciHostBridgeDriver.get();
9102 willEnterFullWake();
9103 promotion = true;
9104 }
9105
9106 // Unsafe to cancel once graphics was powered.
9107 // If system woke from dark wake, the return to sleep can
9108 // be cancelled. "awake -> dark -> sleep" transition
9109 // can be cancelled also, during the "dark -> sleep" phase
9110 // *prior* to driver power down.
9111 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
9112 _pendingCapability == 0) {
9113 options |= kIOPMSyncCancelPowerDown;
9114 }
9115
9116 synchronizePowerTree(options, pciRoot);
9117
9118 if (kFullWakeReasonLocalUser == fullWakeReason) {
9119 // IOGraphics doesn't light the display even though graphics is
9120 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
9121 // So, do an explicit activity tickle
9122 if (wrangler) {
9123 wrangler->activityTickle(0, 0);
9124 }
9125 }
9126
9127 // Log a timestamp for the initial full wake request.
9128 // System may not always honor this full wake request.
9129 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9130 AbsoluteTime now;
9131 uint64_t nsec;
9132
9133 clock_get_uptime(&now);
9134 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9135 absolutetime_to_nanoseconds(now, &nsec);
9136 MSG("full wake %s (reason %u) %u ms\n",
9137 promotion ? "promotion" : "request",
9138 fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9139 }
9140 }
9141
9142 //******************************************************************************
9143 // willEnterFullWake
9144 //
9145 // System will enter full wake from sleep, from dark wake, or from dark
9146 // wake promotion. This function aggregate things that are in common to
9147 // all three full wake transitions.
9148 //
9149 // Assumptions: fullWakeReason was updated
9150 //******************************************************************************
9151
9152 void
9153 IOPMrootDomain::willEnterFullWake( void )
9154 {
9155 hibernateRetry = false;
9156 sleepToStandby = false;
9157 standbyNixed = false;
9158 resetTimers = false;
9159 sleepTimerMaintenance = false;
9160
9161 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9162
9163 _systemMessageClientMask = kSystemMessageClientPowerd |
9164 kSystemMessageClientLegacyApp;
9165
9166 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9167 // First time to attain full wake capability since the last wake
9168 _systemMessageClientMask |= kSystemMessageClientKernel;
9169
9170 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9171 setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9172 (kFullWakeReasonLocalUser == fullWakeReason) ?
9173 kOSBooleanTrue : kOSBooleanFalse);
9174 }
9175 #if HIBERNATION
9176 IOHibernateSetWakeCapabilities(_pendingCapability);
9177 #endif
9178
9179 IOService::setAdvisoryTickleEnable( true );
9180 tellClients(kIOMessageSystemWillPowerOn);
9181 preventTransitionToUserActive(false);
9182 }
9183
9184 //******************************************************************************
9185 // fullWakeDelayedWork
9186 //
9187 // System has already entered full wake. Invoked by a delayed thread call.
9188 //******************************************************************************
9189
9190 void
9191 IOPMrootDomain::fullWakeDelayedWork( void )
9192 {
9193 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9194 if (!gIOPMWorkLoop->inGate()) {
9195 gIOPMWorkLoop->runAction(
9196 OSMemberFunctionCast(IOWorkLoop::Action, this,
9197 &IOPMrootDomain::fullWakeDelayedWork), this);
9198 return;
9199 }
9200
9201 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9202 _currentCapability, _pendingCapability, _highestCapability,
9203 clamshellDisabled, clamshellSleepDisableMask);
9204
9205 if (clamshellExists &&
9206 CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9207 !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9208 if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9209 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9210 } else {
9211 // Not the initial full wake after waking from sleep.
9212 // Evaluate the clamshell for rdar://problem/9157444.
9213 receivePowerNotification(kLocalEvalClamshellCommand);
9214 }
9215 }
9216 #endif
9217 }
9218
9219 //******************************************************************************
9220 // evaluateAssertions
9221 //
9222 //******************************************************************************
9223
9224 // Bitmask of all kernel assertions that prevent system idle sleep.
9225 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9226 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9227 (kIOPMDriverAssertionReservedBit7 | \
9228 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9229
9230 void
9231 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9232 {
9233 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9234
9235 messageClients(kIOPMMessageDriverAssertionsChanged);
9236
9237 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9238 if (wrangler) {
9239 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9240
9241 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9242 wrangler->setIgnoreIdleTimer( value );
9243 }
9244 }
9245
9246 if (changedBits & kIOPMDriverAssertionCPUBit) {
9247 if (_aotNow) {
9248 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9249 }
9250 evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9251 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9252 AbsoluteTime now;
9253 clock_usec_t microsecs;
9254 clock_get_uptime(&now);
9255 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9256 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
9257 if (assertOnWakeReport) {
9258 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9259 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9260 }
9261 }
9262 }
9263
9264 if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9265 if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9266 if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9267 DLOG("PreventIdleSleep driver assertion raised\n");
9268 bool ok = updatePreventIdleSleepList(this, true);
9269 if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9270 // Cancel idle sleep if there is one in progress
9271 cancelIdlePowerDown(this);
9272 }
9273 }
9274 } else {
9275 DLOG("PreventIdleSleep driver assertion dropped\n");
9276 updatePreventIdleSleepList(this, false);
9277 }
9278 }
9279 }
9280
9281 // MARK: -
9282 // MARK: Statistics
9283
9284 //******************************************************************************
9285 // pmStats
9286 //
9287 //******************************************************************************
9288
9289 void
9290 IOPMrootDomain::pmStatsRecordEvent(
9291 int eventIndex,
9292 AbsoluteTime timestamp)
9293 {
9294 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9295 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9296 uint64_t delta;
9297 uint64_t nsec;
9298 OSSharedPtr<OSData> publishPMStats;
9299
9300 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9301
9302 absolutetime_to_nanoseconds(timestamp, &nsec);
9303
9304 switch (eventIndex) {
9305 case kIOPMStatsHibernateImageWrite:
9306 if (starting) {
9307 gPMStats.hibWrite.start = nsec;
9308 } else if (stopping) {
9309 gPMStats.hibWrite.stop = nsec;
9310 }
9311
9312 if (stopping) {
9313 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9314 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9315 }
9316 break;
9317 case kIOPMStatsHibernateImageRead:
9318 if (starting) {
9319 gPMStats.hibRead.start = nsec;
9320 } else if (stopping) {
9321 gPMStats.hibRead.stop = nsec;
9322 }
9323
9324 if (stopping) {
9325 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9326 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9327
9328 publishPMStats = OSData::withValue(gPMStats);
9329 setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9330 bzero(&gPMStats, sizeof(gPMStats));
9331 }
9332 break;
9333 }
9334 }
9335
9336 /*
9337 * Appends a record of the application response to
9338 * IOPMrootDomain::pmStatsAppResponses
9339 */
9340 void
9341 IOPMrootDomain::pmStatsRecordApplicationResponse(
9342 const OSSymbol *response,
9343 const char *name,
9344 int messageType,
9345 uint32_t delay_ms,
9346 uint64_t id,
9347 OSObject *object,
9348 IOPMPowerStateIndex powerState,
9349 bool async)
9350 {
9351 OSSharedPtr<OSDictionary> responseDescription;
9352 OSSharedPtr<OSNumber> delayNum;
9353 OSSharedPtr<OSNumber> powerCaps;
9354 OSSharedPtr<OSNumber> pidNum;
9355 OSSharedPtr<OSNumber> msgNum;
9356 OSSharedPtr<const OSSymbol> appname;
9357 OSSharedPtr<const OSSymbol> sleep;
9358 OSSharedPtr<const OSSymbol> wake;
9359 IOPMServiceInterestNotifier *notify = NULL;
9360
9361 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9362 if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9363 notify->ackTimeoutCnt++;
9364 } else {
9365 notify->ackTimeoutCnt = 0;
9366 }
9367 }
9368
9369 if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9370 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9371 return;
9372 }
9373
9374
9375 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9376 kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9377 } else if (notify) {
9378 // User space app or kernel capability client
9379 if (id) {
9380 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9381 } else {
9382 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9383 }
9384 notify->msgType = 0;
9385 }
9386
9387 responseDescription = OSDictionary::withCapacity(5);
9388 if (responseDescription) {
9389 if (response) {
9390 responseDescription->setObject(_statsResponseTypeKey.get(), response);
9391 }
9392
9393 msgNum = OSNumber::withNumber(messageType, 32);
9394 if (msgNum) {
9395 responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9396 }
9397
9398 if (!name && notify && notify->identifier) {
9399 name = notify->identifier->getCStringNoCopy();
9400 }
9401
9402 if (name && (strlen(name) > 0)) {
9403 appname = OSSymbol::withCString(name);
9404 if (appname) {
9405 responseDescription->setObject(_statsNameKey.get(), appname.get());
9406 }
9407 }
9408
9409 if (!id && notify) {
9410 id = notify->uuid0;
9411 }
9412 pidNum = OSNumber::withNumber(id, 64);
9413 if (pidNum) {
9414 responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9415 }
9416
9417 delayNum = OSNumber::withNumber(delay_ms, 32);
9418 if (delayNum) {
9419 responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9420 }
9421
9422 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9423 powerCaps = OSNumber::withNumber(powerState, 32);
9424
9425 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9426 static const char * driverCallTypes[] = {
9427 [kDriverCallInformPreChange] = "powerStateWillChangeTo",
9428 [kDriverCallInformPostChange] = "powerStateDidChangeTo",
9429 [kDriverCallSetPowerState] = "setPowerState"
9430 };
9431
9432 if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9433 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9434 name, id, driverCallTypes[messageType], (uint32_t) powerState,
9435 async ? "async " : "", delay_ms);
9436 }
9437 #endif
9438 } else {
9439 powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9440 }
9441 if (powerCaps) {
9442 responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9443 }
9444
9445 sleep = OSSymbol::withCString("Sleep");
9446 wake = OSSymbol::withCString("Wake");
9447 if (_systemTransitionType == kSystemTransitionSleep) {
9448 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9449 } else if (_systemTransitionType == kSystemTransitionWake) {
9450 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9451 } else if (_systemTransitionType == kSystemTransitionCapability) {
9452 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9453 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9454 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9455 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9456 }
9457 }
9458
9459 IOLockLock(pmStatsLock);
9460 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9461 pmStatsAppResponses->setObject(responseDescription.get());
9462 }
9463 IOLockUnlock(pmStatsLock);
9464 }
9465
9466 return;
9467 }
9468
9469 // MARK: -
9470 // MARK: PMTraceWorker
9471
9472 //******************************************************************************
9473 // TracePoint support
9474 //
9475 //******************************************************************************
9476
9477 #define kIOPMRegisterNVRAMTracePointHandlerKey \
9478 "IOPMRegisterNVRAMTracePointHandler"
9479
9480 IOReturn
9481 IOPMrootDomain::callPlatformFunction(
9482 const OSSymbol * functionName,
9483 bool waitForFunction,
9484 void * param1, void * param2,
9485 void * param3, void * param4 )
9486 {
9487 if (pmTracer && functionName &&
9488 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9489 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9490 uint32_t tracePointPhases, tracePointPCI;
9491 uint64_t statusCode;
9492
9493 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9494 pmTracer->tracePointTarget = (void *) param2;
9495 tracePointPCI = (uint32_t)(uintptr_t) param3;
9496 tracePointPhases = (uint32_t)(uintptr_t) param4;
9497 if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9498 OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9499 if (node) {
9500 OSSharedPtr<OSObject> bootRomFailureProp;
9501 bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9502 OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9503 uint32_t bootFailureCode;
9504 if (data && data->getLength() == sizeof(bootFailureCode)) {
9505 // Failure code from EFI/BootRom is a four byte structure
9506 memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9507 tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9508 }
9509 }
9510 }
9511 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9512 if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9513 MSG("Sleep failure code 0x%08x 0x%08x\n",
9514 tracePointPCI, tracePointPhases);
9515 }
9516 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9517 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9518
9519 return kIOReturnSuccess;
9520 }
9521 #if HIBERNATION
9522 else if (functionName &&
9523 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9524 if (gSleepPolicyHandler) {
9525 return kIOReturnExclusiveAccess;
9526 }
9527 if (!param1) {
9528 return kIOReturnBadArgument;
9529 }
9530 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9531 gSleepPolicyTarget = (void *) param2;
9532 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9533 return kIOReturnSuccess;
9534 }
9535 #endif
9536
9537 return super::callPlatformFunction(
9538 functionName, waitForFunction, param1, param2, param3, param4);
9539 }
9540
9541 void
9542 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9543 uintptr_t param1, uintptr_t param2, uintptr_t param3)
9544 {
9545 uint32_t code = IODBG_POWER(event);
9546 uint64_t regId = id;
9547 if (regId == 0) {
9548 regId = getRegistryEntryID();
9549 }
9550 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9551 }
9552
9553 void
9554 IOPMrootDomain::tracePoint( uint8_t point )
9555 {
9556 if (systemBooting) {
9557 return;
9558 }
9559
9560 if (kIOPMTracePointWakeCapabilityClients == point) {
9561 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9562 }
9563
9564 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9565 pmTracer->tracePoint(point);
9566 }
9567
9568 static void
9569 kext_log_putc(char c)
9570 {
9571 if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9572 return;
9573 }
9574 if (c == '(' || c == '[' || c == ' ') {
9575 c = 0;
9576 gKextNameEnd = true;
9577 }
9578
9579 gKextNameBuf[gKextNamePos++] = c;
9580 }
9581
9582 static int
9583 kext_log(const char *fmt, ...)
9584 {
9585 va_list listp;
9586
9587 va_start(listp, fmt);
9588 _doprnt(fmt, &listp, &kext_log_putc, 16);
9589 va_end(listp);
9590
9591 return 0;
9592 }
9593
9594 static OSPtr<const OSSymbol>
9595 copyKextIdentifierWithAddress(vm_address_t address)
9596 {
9597 OSSharedPtr<const OSSymbol> identifer;
9598
9599 IOLockLock(gHaltLogLock);
9600
9601 gKextNameEnd = false;
9602 gKextNamePos = 0;
9603 gKextNameBuf[0] = 0;
9604
9605 OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9606 gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9607 identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9608
9609 IOLockUnlock(gHaltLogLock);
9610
9611 return identifer;
9612 }
9613
9614 // Caller serialized using PM workloop
9615 const char *
9616 IOPMrootDomain::getNotificationClientName(OSObject *object)
9617 {
9618 IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9619 const char *clientName = "UNKNOWN";
9620
9621 if (!notifier->clientName) {
9622 // Check for user client
9623 if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9624 OSNumber *clientID = NULL;
9625 messageClient(kIOMessageCopyClientID, object, &clientID);
9626 if (clientID) {
9627 OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9628 if (string) {
9629 notifier->clientName = OSSymbol::withString(string.get());
9630 }
9631 clientID->release();
9632 }
9633 } else if (notifier->identifier) {
9634 notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9635 }
9636 }
9637
9638 if (notifier->clientName) {
9639 clientName = notifier->clientName->getCStringNoCopy();
9640 }
9641
9642 return clientName;
9643 }
9644
9645 void
9646 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9647 {
9648 IOPMServiceInterestNotifier *notifier;
9649
9650 if (systemBooting) {
9651 return;
9652 }
9653 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9654 if (!notifier) {
9655 return;
9656 }
9657
9658 if (start) {
9659 pmTracer->traceDetail(notifier->uuid0 >> 32);
9660 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9661 (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9662
9663 // Update notifier state used for response/ack logging
9664 notifier->msgIndex = msgIndex;
9665 notifier->msgAbsTime = timestamp;
9666
9667 if (msgIndex != UINT_MAX) {
9668 DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9669 } else {
9670 DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9671 }
9672
9673 assert(notifierObject == NULL);
9674 notifierThread = current_thread();
9675 notifierObject.reset(notifier, OSRetain);
9676 } else {
9677 uint64_t nsec;
9678 uint32_t delayMS;
9679
9680 SUB_ABSOLUTETIME(×tamp, ¬ifier->msgAbsTime);
9681 absolutetime_to_nanoseconds(timestamp, &nsec);
9682 delayMS = (uint32_t)(nsec / 1000000ULL);
9683 if (delayMS > notifier->maxMsgDelayMS) {
9684 notifier->maxMsgDelayMS = delayMS;
9685 }
9686
9687 assert(notifierObject == notifier);
9688 notifierObject.reset();
9689 notifierThread = NULL;
9690 }
9691 }
9692
9693 void
9694 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9695 {
9696 if (systemBooting) {
9697 return;
9698 }
9699 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9700 if (!notifier) {
9701 return;
9702 }
9703
9704 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9705 (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9706
9707 DLOG("%s[%u] ack from %s took %d ms\n",
9708 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9709 if (delay_ms > notifier->maxAckDelayMS) {
9710 notifier->maxAckDelayMS = delay_ms;
9711 }
9712 }
9713
9714 void
9715 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9716 {
9717 if (systemBooting) {
9718 return;
9719 }
9720 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9721 if (!notifier) {
9722 return;
9723 }
9724
9725 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9726 (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9727
9728 if (ack_time_us == 0) {
9729 // Client work is done and ack will not be forthcoming
9730 DLOG("%s[%u] response from %s took %d ms\n",
9731 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9732 } else {
9733 // Client needs more time and it must ack within ack_time_us
9734 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9735 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9736 }
9737 }
9738
9739 void
9740 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9741 {
9742 if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9743 return;
9744 }
9745 if (systemBooting) {
9746 return;
9747 }
9748 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9749 if (!notifier) {
9750 return;
9751 }
9752
9753 DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9754 }
9755
9756 void
9757 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9758 {
9759 if (!systemBooting) {
9760 uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
9761 pmTracer->traceDetail( detail );
9762 kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
9763 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
9764 }
9765 }
9766
9767 void
9768 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9769 {
9770 size_t reportSize;
9771 void **report = NULL;
9772 uint32_t bktCnt;
9773 uint32_t bktSize;
9774 uint32_t *clientCnt;
9775
9776 ASSERT_GATED();
9777
9778 report = NULL;
9779 if (channel_id == kAssertDelayChID) {
9780 report = &assertOnWakeReport;
9781 bktCnt = kAssertDelayBcktCnt;
9782 bktSize = kAssertDelayBcktSize;
9783 clientCnt = &assertOnWakeClientCnt;
9784 } else if (channel_id == kSleepDelaysChID) {
9785 report = &sleepDelaysReport;
9786 bktCnt = kSleepDelaysBcktCnt;
9787 bktSize = kSleepDelaysBcktSize;
9788 clientCnt = &sleepDelaysClientCnt;
9789 } else {
9790 assert(false);
9791 return;
9792 }
9793
9794 switch (action) {
9795 case kIOReportEnable:
9796
9797 if (*report) {
9798 (*clientCnt)++;
9799 break;
9800 }
9801
9802 reportSize = HISTREPORT_BUFSIZE(bktCnt);
9803 *report = IOMallocZeroData(reportSize);
9804 if (*report == NULL) {
9805 break;
9806 }
9807 HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9808 getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9809
9810 if (channel_id == kAssertDelayChID) {
9811 assertOnWakeSecs = 0;
9812 }
9813
9814 break;
9815
9816 case kIOReportDisable:
9817 if (*clientCnt == 0) {
9818 break;
9819 }
9820 if (*clientCnt == 1) {
9821 IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
9822 *report = NULL;
9823 }
9824 (*clientCnt)--;
9825
9826 if (channel_id == kAssertDelayChID) {
9827 assertOnWakeSecs = -1; // Invalid value to prevent updates
9828 }
9829 break;
9830
9831 case kIOReportGetDimensions:
9832 if (*report) {
9833 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9834 }
9835 break;
9836 }
9837
9838 return;
9839 }
9840
9841 IOReturn
9842 IOPMrootDomain::configureReport(IOReportChannelList *channelList,
9843 IOReportConfigureAction action,
9844 void *result,
9845 void *destination)
9846 {
9847 unsigned cnt;
9848 uint64_t configAction = (uint64_t)action;
9849
9850 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9851 if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
9852 (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
9853 (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
9854 if (action != kIOReportGetDimensions) {
9855 continue;
9856 }
9857 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
9858 } else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
9859 (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
9860 gIOPMWorkLoop->runAction(
9861 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
9862 (OSObject *)this, (void *)channelList->channels[cnt].channel_id,
9863 (void *)configAction, (void *)result);
9864 }
9865 }
9866
9867 return super::configureReport(channelList, action, result, destination);
9868 }
9869
9870 IOReturn
9871 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9872 {
9873 uint32_t size2cpy;
9874 void *data2cpy;
9875 void **report;
9876
9877 ASSERT_GATED();
9878
9879 report = NULL;
9880 if (ch_id == kAssertDelayChID) {
9881 report = &assertOnWakeReport;
9882 } else if (ch_id == kSleepDelaysChID) {
9883 report = &sleepDelaysReport;
9884 } else {
9885 assert(false);
9886 return kIOReturnBadArgument;
9887 }
9888
9889 if (*report == NULL) {
9890 return kIOReturnNotOpen;
9891 }
9892
9893 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9894 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9895 return kIOReturnOverrun;
9896 }
9897
9898 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9899 dest->appendBytes(data2cpy, size2cpy);
9900
9901 return kIOReturnSuccess;
9902 }
9903
9904 IOReturn
9905 IOPMrootDomain::updateReport(IOReportChannelList *channelList,
9906 IOReportUpdateAction action,
9907 void *result,
9908 void *destination)
9909 {
9910 uint32_t size2cpy;
9911 void *data2cpy;
9912 uint8_t buf[SIMPLEREPORT_BUFSIZE];
9913 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9914 unsigned cnt;
9915 uint64_t ch_id;
9916
9917 if (action != kIOReportCopyChannelData) {
9918 goto exit;
9919 }
9920
9921 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9922 ch_id = channelList->channels[cnt].channel_id;
9923
9924 if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
9925 gIOPMWorkLoop->runAction(
9926 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
9927 (OSObject *)this, (void *)ch_id,
9928 (void *)result, (void *)dest);
9929 continue;
9930 } else if ((ch_id == kSleepCntChID) ||
9931 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9932 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9933 } else {
9934 continue;
9935 }
9936
9937 if (ch_id == kSleepCntChID) {
9938 SIMPLEREPORT_SETVALUE(buf, sleepCnt);
9939 } else if (ch_id == kDarkWkCntChID) {
9940 SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
9941 } else if (ch_id == kUserWkCntChID) {
9942 SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
9943 }
9944
9945 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9946 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9947 dest->appendBytes(data2cpy, size2cpy);
9948 }
9949
9950 exit:
9951 return super::updateReport(channelList, action, result, destination);
9952 }
9953
9954
9955 //******************************************************************************
9956 // PMTraceWorker Class
9957 //
9958 //******************************************************************************
9959
9960 #undef super
9961 #define super OSObject
9962 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9963
9964 #define kPMBestGuessPCIDevicesCount 25
9965 #define kPMMaxRTCBitfieldSize 32
9966
9967 OSPtr<PMTraceWorker>
9968 PMTraceWorker::tracer(IOPMrootDomain * owner)
9969 {
9970 OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9971 if (!me || !me->init()) {
9972 return NULL;
9973 }
9974
9975 DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9976
9977 // Note that we cannot instantiate the PCI device -> bit mappings here, since
9978 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
9979 // this dictionary lazily.
9980 me->owner = owner;
9981 me->pciDeviceBitMappings = NULL;
9982 me->pmTraceWorkerLock = IOLockAlloc();
9983 me->tracePhase = kIOPMTracePointSystemUp;
9984 me->traceData32 = 0;
9985 me->loginWindowData = 0;
9986 me->coreDisplayData = 0;
9987 me->coreGraphicsData = 0;
9988 return me;
9989 }
9990
9991 void
9992 PMTraceWorker::RTC_TRACE(void)
9993 {
9994 if (tracePointHandler && tracePointTarget) {
9995 uint32_t wordA;
9996
9997 IOLockLock(pmTraceWorkerLock);
9998 wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9999 (coreGraphicsData << 8) | tracePhase;
10000 IOLockUnlock(pmTraceWorkerLock);
10001
10002 tracePointHandler( tracePointTarget, traceData32, wordA );
10003 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
10004 }
10005 #if DEVELOPMENT || DEBUG
10006 if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
10007 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
10008 IOLock *l = IOLockAlloc();
10009 IOLockLock(l);
10010 IOLockLock(l);
10011 }
10012 #endif /* DEVELOPMENT || DEBUG */
10013 }
10014
10015 int
10016 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
10017 {
10018 OSSharedPtr<const OSSymbol> deviceName;
10019 int index = -1;
10020
10021 IOLockLock(pmTraceWorkerLock);
10022
10023 if (!pciDeviceBitMappings) {
10024 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
10025 if (!pciDeviceBitMappings) {
10026 goto exit;
10027 }
10028 }
10029
10030 // Check for bitmask overflow.
10031 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
10032 goto exit;
10033 }
10034
10035 if ((deviceName = pciDevice->copyName()) &&
10036 (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
10037 pciDeviceBitMappings->setObject(deviceName.get())) {
10038 index = pciDeviceBitMappings->getCount() - 1;
10039 _LOG("PMTrace PCI array: set object %s => %d\n",
10040 deviceName->getCStringNoCopy(), index);
10041 }
10042
10043 if (!addedToRegistry && (index >= 0)) {
10044 addedToRegistry = owner->setProperty("PCITopLevel", this);
10045 }
10046
10047 exit:
10048 IOLockUnlock(pmTraceWorkerLock);
10049 return index;
10050 }
10051
10052 bool
10053 PMTraceWorker::serialize(OSSerialize *s) const
10054 {
10055 bool ok = false;
10056 if (pciDeviceBitMappings) {
10057 IOLockLock(pmTraceWorkerLock);
10058 ok = pciDeviceBitMappings->serialize(s);
10059 IOLockUnlock(pmTraceWorkerLock);
10060 }
10061 return ok;
10062 }
10063
10064 void
10065 PMTraceWorker::tracePoint(uint8_t phase)
10066 {
10067 // clear trace detail when phase begins
10068 if (tracePhase != phase) {
10069 traceData32 = 0;
10070 }
10071
10072 tracePhase = phase;
10073
10074 DLOG("trace point 0x%02x\n", tracePhase);
10075 RTC_TRACE();
10076 }
10077
10078 void
10079 PMTraceWorker::traceDetail(uint32_t detail)
10080 {
10081 if (detail == traceData32) {
10082 return;
10083 }
10084 traceData32 = detail;
10085 RTC_TRACE();
10086 }
10087
10088 void
10089 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
10090 {
10091 switch (component) {
10092 case kIOPMLoginWindowProgress:
10093 loginWindowData = data & kIOPMLoginWindowProgressMask;
10094 break;
10095 case kIOPMCoreDisplayProgress:
10096 coreDisplayData = data & kIOPMCoreDisplayProgressMask;
10097 break;
10098 case kIOPMCoreGraphicsProgress:
10099 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
10100 break;
10101 default:
10102 return;
10103 }
10104
10105 DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
10106 RTC_TRACE();
10107 }
10108
10109 void
10110 PMTraceWorker::tracePCIPowerChange(
10111 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
10112 {
10113 uint32_t bitMask;
10114 uint32_t expectedFlag;
10115
10116 // Ignore PCI changes outside of system sleep/wake.
10117 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
10118 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
10119 return;
10120 }
10121
10122 // Only record the WillChange transition when going to sleep,
10123 // and the DidChange on the way up.
10124 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
10125 expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
10126 kIOPMDomainWillChange : kIOPMDomainDidChange;
10127 if (changeFlags != expectedFlag) {
10128 return;
10129 }
10130
10131 // Mark this device off in our bitfield
10132 if (bitNum < kPMMaxRTCBitfieldSize) {
10133 bitMask = (1 << bitNum);
10134
10135 if (kPowerChangeStart == type) {
10136 traceData32 |= bitMask;
10137 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
10138 service->getName(), bitNum, bitMask, traceData32);
10139 owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10140 } else {
10141 traceData32 &= ~bitMask;
10142 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10143 service->getName(), bitNum, bitMask, traceData32);
10144 owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10145 }
10146
10147 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10148 RTC_TRACE();
10149 }
10150 }
10151
10152 uint64_t
10153 PMTraceWorker::getPMStatusCode()
10154 {
10155 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10156 }
10157
10158 uint8_t
10159 PMTraceWorker::getTracePhase()
10160 {
10161 return tracePhase;
10162 }
10163
10164 uint32_t
10165 PMTraceWorker::getTraceData()
10166 {
10167 return traceData32;
10168 }
10169
10170 // MARK: -
10171 // MARK: PMHaltWorker
10172
10173 //******************************************************************************
10174 // PMHaltWorker Class
10175 //
10176 //******************************************************************************
10177
10178 PMHaltWorker *
10179 PMHaltWorker::worker( void )
10180 {
10181 PMHaltWorker * me;
10182 IOThread thread;
10183
10184 do {
10185 me = OSTypeAlloc( PMHaltWorker );
10186 if (!me || !me->init()) {
10187 break;
10188 }
10189
10190 me->lock = IOLockAlloc();
10191 if (!me->lock) {
10192 break;
10193 }
10194
10195 DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10196 me->retain(); // thread holds extra retain
10197 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10198 me->release();
10199 break;
10200 }
10201 thread_deallocate(thread);
10202 return me;
10203 } while (false);
10204
10205 if (me) {
10206 me->release();
10207 }
10208 return NULL;
10209 }
10210
10211 void
10212 PMHaltWorker::free( void )
10213 {
10214 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10215 if (lock) {
10216 IOLockFree(lock);
10217 lock = NULL;
10218 }
10219 return OSObject::free();
10220 }
10221
10222 void
10223 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10224 {
10225 PMHaltWorker * me = (PMHaltWorker *) arg;
10226
10227 IOLockLock( gPMHaltLock );
10228 gPMHaltBusyCount++;
10229 me->depth = gPMHaltDepth;
10230 IOLockUnlock( gPMHaltLock );
10231
10232 while (me->depth >= 0) {
10233 PMHaltWorker::work( me );
10234
10235 IOLockLock( gPMHaltLock );
10236 if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10237 // This is the last thread to finish work on this level,
10238 // inform everyone to start working on next lower level.
10239 gPMHaltDepth--;
10240 me->depth = gPMHaltDepth;
10241 gPMHaltIdleCount = 0;
10242 thread_wakeup((event_t) &gPMHaltIdleCount);
10243 } else {
10244 // One or more threads are still working on this level,
10245 // this thread must wait.
10246 me->depth = gPMHaltDepth - 1;
10247 do {
10248 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10249 } while (me->depth != gPMHaltDepth);
10250 }
10251 IOLockUnlock( gPMHaltLock );
10252 }
10253
10254 // No more work to do, terminate thread
10255 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10256 thread_wakeup( &gPMHaltDepth );
10257 me->release();
10258 }
10259
10260 void
10261 PMHaltWorker::work( PMHaltWorker * me )
10262 {
10263 OSSharedPtr<IOService> service;
10264 OSSet * inner;
10265 AbsoluteTime startTime, elapsedTime;
10266 UInt32 deltaTime;
10267 bool timeout;
10268
10269 while (true) {
10270 timeout = false;
10271
10272 // Claim an unit of work from the shared pool
10273 IOLockLock( gPMHaltLock );
10274 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10275 if (inner) {
10276 service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10277 if (service) {
10278 inner->removeObject(service.get());
10279 }
10280 }
10281 IOLockUnlock( gPMHaltLock );
10282 if (!service) {
10283 break; // no more work at this depth
10284 }
10285 clock_get_uptime(&startTime);
10286
10287 if (!service->isInactive() &&
10288 service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10289 IOLockLock(me->lock);
10290 me->startTime = startTime;
10291 me->service = service.get();
10292 me->timeout = false;
10293 IOLockUnlock(me->lock);
10294
10295 service->systemWillShutdown( gPMHaltMessageType);
10296
10297 // Wait for driver acknowledgement
10298 IOLockLock(me->lock);
10299 while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10300 IOLockSleep(me->lock, me, THREAD_UNINT);
10301 }
10302 me->service = NULL;
10303 timeout = me->timeout;
10304 IOLockUnlock(me->lock);
10305 }
10306
10307 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10308 if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10309 LOG("%s driver %s (0x%llx) took %u ms\n",
10310 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10311 "PowerOff" : "Restart",
10312 service->getName(), service->getRegistryEntryID(),
10313 (uint32_t) deltaTime );
10314 halt_log_enter("PowerOff/Restart handler completed",
10315 OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10316 elapsedTime);
10317 }
10318
10319 me->visits++;
10320 }
10321 }
10322
10323 void
10324 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10325 {
10326 UInt64 nano;
10327 AbsoluteTime startTime;
10328 AbsoluteTime endTime;
10329
10330 endTime = *now;
10331
10332 IOLockLock(me->lock);
10333 if (me->service && !me->timeout) {
10334 startTime = me->startTime;
10335 nano = 0;
10336 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10337 SUB_ABSOLUTETIME(&endTime, &startTime);
10338 absolutetime_to_nanoseconds(endTime, &nano);
10339 }
10340 if (nano > 3000000000ULL) {
10341 me->timeout = true;
10342
10343 halt_log_enter("PowerOff/Restart still waiting on handler",
10344 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10345 endTime);
10346 MSG("%s still waiting on %s\n",
10347 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart",
10348 me->service->getName());
10349 }
10350 }
10351 IOLockUnlock(me->lock);
10352 }
10353
10354 //******************************************************************************
10355 // acknowledgeSystemWillShutdown
10356 //
10357 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10358 //******************************************************************************
10359
10360 void
10361 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10362 {
10363 PMHaltWorker * worker;
10364 OSSharedPtr<OSObject> prop;
10365
10366 if (!from) {
10367 return;
10368 }
10369
10370 //DLOG("%s acknowledged\n", from->getName());
10371 prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10372 if (prop) {
10373 worker = (PMHaltWorker *) prop.get();
10374 IOLockLock(worker->lock);
10375 from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10376 thread_wakeup((event_t) worker);
10377 IOLockUnlock(worker->lock);
10378 } else {
10379 DLOG("%s acknowledged without worker property\n",
10380 from->getName());
10381 }
10382 }
10383
10384
10385 //******************************************************************************
10386 // notifySystemShutdown
10387 //
10388 // Notify all objects in PM tree that system will shutdown or restart
10389 //******************************************************************************
10390
10391 static void
10392 notifySystemShutdown( IOService * root, uint32_t messageType )
10393 {
10394 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10395 OSSharedPtr<IORegistryIterator> iter;
10396 IORegistryEntry * entry;
10397 IOService * node;
10398 OSSet * inner;
10399 OSSharedPtr<OSSet> newInner;
10400 PMHaltWorker * workers[kPMHaltMaxWorkers];
10401 AbsoluteTime deadline;
10402 unsigned int totalNodes = 0;
10403 unsigned int depth;
10404 unsigned int rootDepth;
10405 unsigned int numWorkers;
10406 unsigned int count;
10407 int waitResult;
10408 void * baseFunc;
10409 bool ok;
10410
10411 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10412
10413 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10414
10415 // Iterate the entire PM tree starting from root
10416
10417 rootDepth = root->getDepth( gIOPowerPlane );
10418 if (!rootDepth) {
10419 goto done;
10420 }
10421
10422 // debug - for repeated test runs
10423 while (PMHaltWorker::metaClass->getInstanceCount()) {
10424 IOSleep(1);
10425 }
10426
10427 if (!gPMHaltArray) {
10428 gPMHaltArray = OSArray::withCapacity(40);
10429 if (!gPMHaltArray) {
10430 goto done;
10431 }
10432 } else { // debug
10433 gPMHaltArray->flushCollection();
10434 }
10435
10436 if (!gPMHaltLock) {
10437 gPMHaltLock = IOLockAlloc();
10438 if (!gPMHaltLock) {
10439 goto done;
10440 }
10441 }
10442
10443 if (!gPMHaltClientAcknowledgeKey) {
10444 gPMHaltClientAcknowledgeKey =
10445 OSSymbol::withCStringNoCopy("PMShutdown");
10446 if (!gPMHaltClientAcknowledgeKey) {
10447 goto done;
10448 }
10449 }
10450
10451 gPMHaltMessageType = messageType;
10452
10453 // Depth-first walk of PM plane
10454
10455 iter = IORegistryIterator::iterateOver(
10456 root, gIOPowerPlane, kIORegistryIterateRecursively);
10457
10458 if (iter) {
10459 while ((entry = iter->getNextObject())) {
10460 node = OSDynamicCast(IOService, entry);
10461 if (!node) {
10462 continue;
10463 }
10464
10465 if (baseFunc ==
10466 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10467 continue;
10468 }
10469
10470 depth = node->getDepth( gIOPowerPlane );
10471 if (depth <= rootDepth) {
10472 continue;
10473 }
10474
10475 ok = false;
10476
10477 // adjust to zero based depth
10478 depth -= (rootDepth + 1);
10479
10480 // gPMHaltArray is an array of containers, each container
10481 // refers to nodes with the same depth.
10482
10483 count = gPMHaltArray->getCount();
10484 while (depth >= count) {
10485 // expand array and insert placeholders
10486 gPMHaltArray->setObject(PLACEHOLDER);
10487 count++;
10488 }
10489 count = gPMHaltArray->getCount();
10490 if (depth < count) {
10491 inner = (OSSet *)gPMHaltArray->getObject(depth);
10492 if (inner == PLACEHOLDER) {
10493 newInner = OSSet::withCapacity(40);
10494 if (newInner) {
10495 gPMHaltArray->replaceObject(depth, newInner.get());
10496 inner = newInner.get();
10497 }
10498 }
10499
10500 // PM nodes that appear more than once in the tree will have
10501 // the same depth, OSSet will refuse to add the node twice.
10502 if (inner) {
10503 ok = inner->setObject(node);
10504 }
10505 }
10506 if (!ok) {
10507 DLOG("Skipped PM node %s\n", node->getName());
10508 }
10509 }
10510 }
10511
10512 // debug only
10513 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10514 count = 0;
10515 if (inner != PLACEHOLDER) {
10516 count = inner->getCount();
10517 }
10518 DLOG("Nodes at depth %u = %u\n", i, count);
10519 }
10520
10521 // strip placeholders (not all depths are populated)
10522 numWorkers = 0;
10523 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10524 if (inner == PLACEHOLDER) {
10525 gPMHaltArray->removeObject(i);
10526 continue;
10527 }
10528 count = inner->getCount();
10529 if (count > numWorkers) {
10530 numWorkers = count;
10531 }
10532 totalNodes += count;
10533 i++;
10534 }
10535
10536 if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10537 goto done;
10538 }
10539
10540 gPMHaltBusyCount = 0;
10541 gPMHaltIdleCount = 0;
10542 gPMHaltDepth = gPMHaltArray->getCount() - 1;
10543
10544 // Create multiple workers (and threads)
10545
10546 if (numWorkers > kPMHaltMaxWorkers) {
10547 numWorkers = kPMHaltMaxWorkers;
10548 }
10549
10550 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10551 totalNodes, gPMHaltArray->getCount(), numWorkers);
10552
10553 for (unsigned int i = 0; i < numWorkers; i++) {
10554 workers[i] = PMHaltWorker::worker();
10555 }
10556
10557 // Wait for workers to exhaust all available work
10558
10559 IOLockLock(gPMHaltLock);
10560 while (gPMHaltDepth >= 0) {
10561 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10562
10563 waitResult = IOLockSleepDeadline(
10564 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10565 if (THREAD_TIMED_OUT == waitResult) {
10566 AbsoluteTime now;
10567 clock_get_uptime(&now);
10568
10569 IOLockUnlock(gPMHaltLock);
10570 for (unsigned int i = 0; i < numWorkers; i++) {
10571 if (workers[i]) {
10572 PMHaltWorker::checkTimeout(workers[i], &now);
10573 }
10574 }
10575 IOLockLock(gPMHaltLock);
10576 }
10577 }
10578 IOLockUnlock(gPMHaltLock);
10579
10580 // Release all workers
10581
10582 for (unsigned int i = 0; i < numWorkers; i++) {
10583 if (workers[i]) {
10584 workers[i]->release();
10585 }
10586 // worker also retained by it's own thread
10587 }
10588
10589 done:
10590 DLOG("%s done\n", __FUNCTION__);
10591 return;
10592 }
10593
10594 // MARK: -
10595 // MARK: Kernel Assertion
10596
10597 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10598
10599 IOPMDriverAssertionID
10600 IOPMrootDomain::createPMAssertion(
10601 IOPMDriverAssertionType whichAssertionBits,
10602 IOPMDriverAssertionLevel assertionLevel,
10603 IOService *ownerService,
10604 const char *ownerDescription)
10605 {
10606 IOReturn ret;
10607 IOPMDriverAssertionID newAssertion;
10608
10609 if (!pmAssertions) {
10610 return 0;
10611 }
10612
10613 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10614
10615 if (kIOReturnSuccess == ret) {
10616 #if (DEVELOPMENT || DEBUG)
10617 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10618 const char *serviceName = (ownerService && ownerService->reserved) ? ownerService->getName() : NULL;
10619 OSReportWithBacktrace("PMRD: createPMAssertion(0x%qx) %s (%s)", newAssertion,
10620 serviceName, ownerDescription);
10621 }
10622 #endif /* (DEVELOPMENT || DEBUG) */
10623 return newAssertion;
10624 } else {
10625 return 0;
10626 }
10627 }
10628
10629 IOReturn
10630 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10631 {
10632 #if (DEVELOPMENT || DEBUG)
10633 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10634 PMAssertStruct *details = pmAssertions->detailsForID(releaseAssertion, NULL);
10635 if (details) {
10636 const char *serviceName = (details->ownerService && details->ownerService->reserved) ?
10637 details->ownerService->getName() : NULL;
10638 const char *ownerString = details->ownerString ? details->ownerString->getCStringNoCopy() : NULL;
10639 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx) %s (%s)", releaseAssertion, serviceName, ownerString);
10640 } else {
10641 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx)", releaseAssertion);
10642 }
10643 }
10644 #endif /* (DEVELOPMENT || DEBUG) */
10645 if (!pmAssertions) {
10646 return kIOReturnInternalError;
10647 }
10648 return pmAssertions->releaseAssertion(releaseAssertion);
10649 }
10650
10651
10652 IOReturn
10653 IOPMrootDomain::setPMAssertionLevel(
10654 IOPMDriverAssertionID assertionID,
10655 IOPMDriverAssertionLevel assertionLevel)
10656 {
10657 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10658 }
10659
10660 IOPMDriverAssertionLevel
10661 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10662 {
10663 IOPMDriverAssertionType sysLevels;
10664
10665 if (!pmAssertions || whichAssertion == 0) {
10666 return kIOPMDriverAssertionLevelOff;
10667 }
10668
10669 sysLevels = pmAssertions->getActivatedAssertions();
10670
10671 // Check that every bit set in argument 'whichAssertion' is asserted
10672 // in the aggregate bits.
10673 if ((sysLevels & whichAssertion) == whichAssertion) {
10674 return kIOPMDriverAssertionLevelOn;
10675 } else {
10676 return kIOPMDriverAssertionLevelOff;
10677 }
10678 }
10679
10680 IOReturn
10681 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10682 {
10683 if (!pmAssertions) {
10684 return kIOReturnNotFound;
10685 }
10686
10687 return pmAssertions->setUserAssertionLevels(inLevels);
10688 }
10689
10690 IOReturn
10691 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10692 {
10693 return gIOPMWorkLoop->runActionBlock(^{
10694 if (_driverKitMatchingAssertionCount != 0) {
10695 _driverKitMatchingAssertionCount++;
10696 return kIOReturnSuccess;
10697 } else {
10698 if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
10699 // system going to sleep
10700 return kIOReturnBusy;
10701 } else {
10702 // createPMAssertion is asynchronous.
10703 // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10704 // The assertion is used so that on release, we reevaluate all assertions
10705 _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10706 if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10707 _driverKitMatchingAssertionCount = 1;
10708 return kIOReturnSuccess;
10709 } else {
10710 return kIOReturnBusy;
10711 }
10712 }
10713 }
10714 });
10715 }
10716
10717 void
10718 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10719 {
10720 gIOPMWorkLoop->runActionBlock(^{
10721 if (_driverKitMatchingAssertionCount != 0) {
10722 _driverKitMatchingAssertionCount--;
10723 if (_driverKitMatchingAssertionCount == 0) {
10724 releasePMAssertion(_driverKitMatchingAssertion);
10725 _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10726 }
10727 } else {
10728 panic("Over-release of driverkit matching assertion");
10729 }
10730 return kIOReturnSuccess;
10731 });
10732 }
10733
10734 bool
10735 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10736 {
10737 if (pmAssertions) {
10738 pmAssertions->publishProperties();
10739 }
10740 return IOService::serializeProperties(s);
10741 }
10742
10743 OSSharedPtr<OSObject>
10744 IOPMrootDomain::copyProperty( const char * aKey) const
10745 {
10746 OSSharedPtr<OSObject> obj;
10747 obj = IOService::copyProperty(aKey);
10748
10749 if (obj) {
10750 return obj;
10751 }
10752
10753 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10754 sizeof(kIOPMSleepWakeWdogRebootKey))) {
10755 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10756 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10757 } else {
10758 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10759 }
10760 }
10761
10762 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10763 sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10764 if (swd_flags & SWD_VALID_LOGS) {
10765 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10766 } else {
10767 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10768 }
10769 }
10770
10771 /*
10772 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
10773 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10774 * issued by DisplayWrangler on darkwake.
10775 */
10776 if (!strcmp(aKey, "DesktopMode")) {
10777 if (desktopMode) {
10778 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10779 } else {
10780 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10781 }
10782 }
10783 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10784 if (displayIdleForDemandSleep) {
10785 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10786 } else {
10787 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10788 }
10789 }
10790
10791 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10792 OSSharedPtr<OSArray> array;
10793 WAKEEVENT_LOCK();
10794 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10795 OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10796 if (collection) {
10797 array = OSDynamicPtrCast<OSArray>(collection);
10798 }
10799 }
10800 WAKEEVENT_UNLOCK();
10801 return os::move(array);
10802 }
10803
10804 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10805 OSSharedPtr<OSArray> array;
10806 IOLockLock(pmStatsLock);
10807 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10808 OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10809 if (collection) {
10810 array = OSDynamicPtrCast<OSArray>(collection);
10811 }
10812 }
10813 IOLockUnlock(pmStatsLock);
10814 return os::move(array);
10815 }
10816
10817 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10818 OSArray *idleSleepList = NULL;
10819 gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10820 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10821 }
10822
10823 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10824 OSArray *systemSleepList = NULL;
10825 gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10826 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10827 }
10828
10829 if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10830 OSArray *idleSleepList = NULL;
10831 gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10832 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10833 }
10834
10835 if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10836 OSArray *systemSleepList = NULL;
10837 gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10838 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10839 }
10840 return NULL;
10841 }
10842
10843 // MARK: -
10844 // MARK: Wake Event Reporting
10845
10846 void
10847 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10848 {
10849 WAKEEVENT_LOCK();
10850 strlcpy(outBuf, gWakeReasonString, bufSize);
10851 WAKEEVENT_UNLOCK();
10852 }
10853
10854 void
10855 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10856 {
10857 WAKEEVENT_LOCK();
10858 strlcpy(outBuf, gShutdownReasonString, bufSize);
10859 WAKEEVENT_UNLOCK();
10860 }
10861
10862 //******************************************************************************
10863 // acceptSystemWakeEvents
10864 //
10865 // Private control for the acceptance of driver wake event claims.
10866 //******************************************************************************
10867
10868 void
10869 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10870 {
10871 bool logWakeReason = false;
10872
10873 WAKEEVENT_LOCK();
10874 switch (control) {
10875 case kAcceptSystemWakeEvents_Enable:
10876 assert(_acceptSystemWakeEvents == false);
10877 if (!_systemWakeEventsArray) {
10878 _systemWakeEventsArray = OSArray::withCapacity(4);
10879 }
10880 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10881 if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10882 gWakeReasonString[0] = '\0';
10883 if (_systemWakeEventsArray) {
10884 _systemWakeEventsArray->flushCollection();
10885 }
10886 }
10887
10888 // Remove stale WakeType property before system sleep
10889 removeProperty(kIOPMRootDomainWakeTypeKey);
10890 removeProperty(kIOPMRootDomainWakeReasonKey);
10891 break;
10892
10893 case kAcceptSystemWakeEvents_Disable:
10894 _acceptSystemWakeEvents = false;
10895 #if defined(XNU_TARGET_OS_OSX)
10896 logWakeReason = (gWakeReasonString[0] != '\0');
10897 #else /* !defined(XNU_TARGET_OS_OSX) */
10898 logWakeReason = gWakeReasonSysctlRegistered;
10899 #if DEVELOPMENT
10900 static int panic_allowed = -1;
10901
10902 if ((panic_allowed == -1) &&
10903 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10904 panic_allowed = 0;
10905 }
10906
10907 if (panic_allowed) {
10908 size_t i = 0;
10909 // Panic if wake reason is null or empty
10910 for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10911 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10912 break;
10913 }
10914 }
10915 if (i >= strlen(gWakeReasonString)) {
10916 panic("Wake reason is empty");
10917 }
10918 }
10919 #endif /* DEVELOPMENT */
10920 #endif /* !defined(XNU_TARGET_OS_OSX) */
10921
10922 // publish kIOPMRootDomainWakeReasonKey if not already set
10923 if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10924 setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10925 }
10926 break;
10927
10928 case kAcceptSystemWakeEvents_Reenable:
10929 assert(_acceptSystemWakeEvents == false);
10930 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10931 removeProperty(kIOPMRootDomainWakeReasonKey);
10932 break;
10933 }
10934 WAKEEVENT_UNLOCK();
10935
10936 if (logWakeReason) {
10937 MSG("system wake events: %s\n", gWakeReasonString);
10938 }
10939 }
10940
10941 //******************************************************************************
10942 // claimSystemWakeEvent
10943 //
10944 // For a driver to claim a device is the source/conduit of a system wake event.
10945 //******************************************************************************
10946
10947 void
10948 IOPMrootDomain::claimSystemWakeEvent(
10949 IOService * device,
10950 IOOptionBits flags,
10951 const char * reason,
10952 OSObject * details )
10953 {
10954 OSSharedPtr<const OSSymbol> deviceName;
10955 OSSharedPtr<OSNumber> deviceRegId;
10956 OSSharedPtr<OSNumber> claimTime;
10957 OSSharedPtr<OSData> flagsData;
10958 OSSharedPtr<OSString> reasonString;
10959 OSSharedPtr<OSDictionary> dict;
10960 uint64_t timestamp;
10961 bool addWakeReason;
10962
10963 if (!device || !reason) {
10964 return;
10965 }
10966
10967 pmEventTimeStamp(×tamp);
10968
10969 uint64_t args[3] = {};
10970 strlcpy((char *)args, reason, sizeof(args));
10971 kdebugTrace(kPMLogClaimSystemWake, args[0], args[1], args[2], device->getRegistryEntryID());
10972
10973 IOOptionBits aotFlags = 0;
10974 bool needAOTEvaluate = FALSE;
10975
10976 if (kIOPMAOTModeAddEventFlags & _aotMode) {
10977 // Only allow lingering in AOT_STATE for the two wake reasons used for the wrist raise gesture.
10978 if (strcmp("AOP.OutboxNotEmpty", reason) && strcmp("spu_gesture", reason)) {
10979 flags |= kIOPMWakeEventAOTExit;
10980 }
10981 }
10982
10983 #if DEVELOPMENT || DEBUG
10984 if (_aotLingerTime && !strcmp("rtc", reason)) {
10985 flags |= kIOPMWakeEventAOTPossibleExit;
10986 }
10987 #endif /* DEVELOPMENT || DEBUG */
10988
10989 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10990 // Publishing the WakeType is serialized by the PM work loop
10991 if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
10992 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10993 (void *) _nextScheduledAlarmType.get());
10994 }
10995
10996 // Workaround for the missing wake HID event
10997 if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
10998 if (!strcmp("trackpadkeyboard", reason)) {
10999 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
11000 (void *) gIOPMWakeTypeUserKey.get());
11001 }
11002 }
11003 #endif
11004
11005 deviceName = device->copyName(gIOServicePlane);
11006 deviceRegId = OSNumber::withNumber(device->getRegistryEntryID(), 64);
11007 claimTime = OSNumber::withNumber(timestamp, 64);
11008 flagsData = OSData::withValue(flags);
11009 reasonString = OSString::withCString(reason);
11010 dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
11011 if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
11012 goto done;
11013 }
11014
11015 dict->setObject(gIONameKey, deviceName.get());
11016 dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
11017 dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
11018 dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
11019 dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
11020 if (details) {
11021 dict->setObject(kIOPMWakeEventDetailsKey, details);
11022 }
11023
11024 WAKEEVENT_LOCK();
11025 addWakeReason = _acceptSystemWakeEvents;
11026 if (_aotMode) {
11027 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
11028 }
11029 aotFlags = (kIOPMWakeEventAOTFlags & flags);
11030 aotFlags = (aotFlags & ~_aotPendingFlags);
11031 needAOTEvaluate = false;
11032 if (_aotNow && aotFlags) {
11033 if (kIOPMWakeEventAOTPossibleExit & flags) {
11034 _aotMetrics->possibleCount++;
11035 }
11036 if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
11037 _aotMetrics->confirmedPossibleCount++;
11038 }
11039 if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
11040 _aotMetrics->rejectedPossibleCount++;
11041 }
11042 if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
11043 _aotMetrics->expiredPossibleCount++;
11044 }
11045
11046 _aotPendingFlags |= aotFlags;
11047 addWakeReason = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
11048 needAOTEvaluate = _aotReadyToFullWake;
11049 }
11050 DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
11051 reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
11052 _aotNow, pmTracer->getTracePhase(), addWakeReason);
11053
11054 #if DEVELOPMENT || DEBUG
11055 if (addWakeReason) {
11056 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11057 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11058 "Report System Wake Event",
11059 "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
11060 reason,
11061 (int)flags,
11062 deviceName->getCStringNoCopy(),
11063 device->getRegistryEntryID()
11064 );
11065 }
11066 #endif /* DEVELOPMENT || DEBUG */
11067
11068 if (!gWakeReasonSysctlRegistered) {
11069 // Lazy registration until the platform driver stops registering
11070 // the same name.
11071 gWakeReasonSysctlRegistered = true;
11072 }
11073 if (addWakeReason) {
11074 _systemWakeEventsArray->setObject(dict.get());
11075 if (gWakeReasonString[0] != '\0') {
11076 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
11077 }
11078 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
11079 }
11080
11081 WAKEEVENT_UNLOCK();
11082 if (needAOTEvaluate) {
11083 // Call aotEvaluate() on PM work loop since it may call
11084 // aotExit() which accesses PM state.
11085 pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
11086 }
11087
11088 done:
11089 return;
11090 }
11091
11092 //******************************************************************************
11093 // claimSystemBootEvent
11094 //
11095 // For a driver to claim a device is the source/conduit of a system boot event.
11096 //******************************************************************************
11097
11098 void
11099 IOPMrootDomain::claimSystemBootEvent(
11100 IOService * device,
11101 IOOptionBits flags,
11102 const char * reason,
11103 __unused OSObject * details )
11104 {
11105 if (!device || !reason) {
11106 return;
11107 }
11108
11109 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11110 #if DEVELOPMENT || DEBUG
11111 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11112 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11113 "Report System Boot Device",
11114 "Reason: %s Flags: 0x%x Device: %s",
11115 reason,
11116 (int)flags,
11117 device->getName()
11118 );
11119 #endif /* DEVELOPMENT || DEBUG */
11120 WAKEEVENT_LOCK();
11121 if (!gBootReasonSysctlRegistered) {
11122 // Lazy sysctl registration after setting gBootReasonString
11123 strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
11124 os_atomic_store(&gBootReasonSysctlRegistered, true, release);
11125 }
11126 WAKEEVENT_UNLOCK();
11127 }
11128
11129 //******************************************************************************
11130 // claimSystemShutdownEvent
11131 //
11132 // For drivers to claim a system shutdown event on the ensuing boot.
11133 //******************************************************************************
11134
11135 void
11136 IOPMrootDomain::claimSystemShutdownEvent(
11137 IOService * device,
11138 IOOptionBits flags,
11139 const char * reason,
11140 __unused OSObject * details )
11141 {
11142 if (!device || !reason) {
11143 return;
11144 }
11145
11146 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11147 #if DEVELOPMENT || DEBUG
11148 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11149 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11150 "Report System Shutdown Cause From Previous Boot",
11151 "Reason: %s Flags: 0x%x Device: %s",
11152 reason,
11153 (int)flags,
11154 device->getName()
11155 );
11156 #endif /* DEVELOPMENT || DEBUG */
11157 WAKEEVENT_LOCK();
11158 if (gShutdownReasonString[0] != '\0') {
11159 strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11160 }
11161 strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11162
11163 gShutdownReasonSysctlRegistered = true;
11164 WAKEEVENT_UNLOCK();
11165 }
11166
11167 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11168
11169 // MARK: -
11170 // MARK: PMSettingHandle
11171
11172 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11173
11174 void
11175 PMSettingHandle::free( void )
11176 {
11177 if (pmso) {
11178 pmso->clientHandleFreed();
11179 pmso->release();
11180 pmso = NULL;
11181 }
11182
11183 OSObject::free();
11184 }
11185
11186 // MARK: -
11187 // MARK: PMSettingObject
11188
11189 #undef super
11190 #define super OSObject
11191 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11192
11193 /*
11194 * Static constructor/initializer for PMSettingObject
11195 */
11196 PMSettingObject *PMSettingObject::pmSettingObject(
11197 IOPMrootDomain * parent_arg,
11198 IOPMSettingControllerCallback handler_arg,
11199 OSObject * target_arg,
11200 uintptr_t refcon_arg,
11201 uint32_t supportedPowerSources,
11202 const OSSymbol * settings[],
11203 OSObject * *handle_obj)
11204 {
11205 uint32_t settingCount = 0;
11206 PMSettingObject *pmso = NULL;
11207 PMSettingHandle *pmsh = NULL;
11208
11209 if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11210 return NULL;
11211 }
11212
11213 // count OSSymbol entries in NULL terminated settings array
11214 while (settings[settingCount]) {
11215 settingCount++;
11216 }
11217 if (0 == settingCount) {
11218 return NULL;
11219 }
11220
11221 pmso = new PMSettingObject;
11222 if (!pmso || !pmso->init()) {
11223 goto fail;
11224 }
11225
11226 pmsh = new PMSettingHandle;
11227 if (!pmsh || !pmsh->init()) {
11228 goto fail;
11229 }
11230
11231 queue_init(&pmso->calloutQueue);
11232 pmso->parent = parent_arg;
11233 pmso->func = handler_arg;
11234 pmso->target = target_arg;
11235 pmso->refcon = refcon_arg;
11236 pmso->settingCount = settingCount;
11237
11238 pmso->retain(); // handle holds a retain on pmso
11239 pmsh->pmso = pmso;
11240 pmso->pmsh = pmsh;
11241
11242 pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11243 if (pmso->publishedFeatureID) {
11244 for (unsigned int i = 0; i < settingCount; i++) {
11245 // Since there is now at least one listener to this setting, publish
11246 // PM root domain support for it.
11247 parent_arg->publishPMSetting( settings[i],
11248 supportedPowerSources, &pmso->publishedFeatureID[i] );
11249 }
11250 }
11251
11252 *handle_obj = pmsh;
11253 return pmso;
11254
11255 fail:
11256 if (pmso) {
11257 pmso->release();
11258 }
11259 if (pmsh) {
11260 pmsh->release();
11261 }
11262 return NULL;
11263 }
11264
11265 void
11266 PMSettingObject::free( void )
11267 {
11268 if (publishedFeatureID) {
11269 for (const auto& featureID : publishedFeatureID) {
11270 if (featureID) {
11271 parent->removePublishedFeature( featureID );
11272 }
11273 }
11274
11275 publishedFeatureID = {};
11276 }
11277
11278 super::free();
11279 }
11280
11281 IOReturn
11282 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11283 {
11284 return (*func)(target, type, object, refcon);
11285 }
11286
11287 void
11288 PMSettingObject::clientHandleFreed( void )
11289 {
11290 parent->deregisterPMSettingObject(this);
11291 }
11292
11293 // MARK: -
11294 // MARK: PMAssertionsTracker
11295
11296 //*********************************************************************************
11297 //*********************************************************************************
11298 //*********************************************************************************
11299 // class PMAssertionsTracker Implementation
11300
11301 #define kAssertUniqueIDStart 500
11302
11303 PMAssertionsTracker *
11304 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11305 {
11306 PMAssertionsTracker *me;
11307
11308 me = new PMAssertionsTracker;
11309 if (!me || !me->init()) {
11310 if (me) {
11311 me->release();
11312 }
11313 return NULL;
11314 }
11315
11316 me->owner = rootDomain;
11317 me->issuingUniqueID = kAssertUniqueIDStart;
11318 me->assertionsArray = OSArray::withCapacity(5);
11319 me->assertionsKernel = 0;
11320 me->assertionsUser = 0;
11321 me->assertionsCombined = 0;
11322 me->assertionsArrayLock = IOLockAlloc();
11323 me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11324
11325 assert(me->assertionsArray);
11326 assert(me->assertionsArrayLock);
11327
11328 return me;
11329 }
11330
11331 /* tabulate
11332 * - Update assertionsKernel to reflect the state of all
11333 * assertions in the kernel.
11334 * - Update assertionsCombined to reflect both kernel & user space.
11335 */
11336 void
11337 PMAssertionsTracker::tabulate(void)
11338 {
11339 int i;
11340 int count;
11341 const PMAssertStruct *_a = nullptr;
11342 OSValueObject<PMAssertStruct> *_d = nullptr;
11343
11344 IOPMDriverAssertionType oldKernel = assertionsKernel;
11345 IOPMDriverAssertionType oldCombined = assertionsCombined;
11346
11347 ASSERT_GATED();
11348
11349 assertionsKernel = 0;
11350 assertionsCombined = 0;
11351
11352 if (!assertionsArray) {
11353 return;
11354 }
11355
11356 if ((count = assertionsArray->getCount())) {
11357 for (i = 0; i < count; i++) {
11358 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11359 if (_d) {
11360 _a = _d->getBytesNoCopy();
11361 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11362 assertionsKernel |= _a->assertionBits;
11363 }
11364 }
11365 }
11366 }
11367
11368 tabulateProducerCount++;
11369 assertionsCombined = assertionsKernel | assertionsUser;
11370
11371 if ((assertionsKernel != oldKernel) ||
11372 (assertionsCombined != oldCombined)) {
11373 owner->evaluateAssertions(assertionsCombined, oldCombined);
11374 }
11375 }
11376
11377 void
11378 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11379 {
11380 AbsoluteTime now;
11381 uint64_t nsec;
11382
11383 if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11384 (assertStruct->assertCPUStartTime == 0)) {
11385 return;
11386 }
11387
11388 now = mach_absolute_time();
11389 SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11390 absolutetime_to_nanoseconds(now, &nsec);
11391 assertStruct->assertCPUDuration += nsec;
11392 assertStruct->assertCPUStartTime = 0;
11393
11394 if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11395 maxAssertCPUDuration = assertStruct->assertCPUDuration;
11396 maxAssertCPUEntryId = assertStruct->registryEntryID;
11397 }
11398 }
11399
11400 void
11401 PMAssertionsTracker::reportCPUBitAccounting( void )
11402 {
11403 const PMAssertStruct *_a = nullptr;
11404 OSValueObject<PMAssertStruct> *_d = nullptr;
11405 int i, count;
11406 AbsoluteTime now;
11407 uint64_t nsec;
11408
11409 ASSERT_GATED();
11410
11411 // Account for drivers that are still holding the CPU assertion
11412 if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11413 now = mach_absolute_time();
11414 if ((count = assertionsArray->getCount())) {
11415 for (i = 0; i < count; i++) {
11416 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11417 if (_d) {
11418 _a = _d->getBytesNoCopy();
11419 if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11420 (_a->level == kIOPMDriverAssertionLevelOn) &&
11421 (_a->assertCPUStartTime != 0)) {
11422 // Don't modify PMAssertStruct, leave that
11423 // for updateCPUBitAccounting()
11424 SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11425 absolutetime_to_nanoseconds(now, &nsec);
11426 nsec += _a->assertCPUDuration;
11427 if (nsec > maxAssertCPUDuration) {
11428 maxAssertCPUDuration = nsec;
11429 maxAssertCPUEntryId = _a->registryEntryID;
11430 }
11431 }
11432 }
11433 }
11434 }
11435 }
11436
11437 if (maxAssertCPUDuration) {
11438 DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11439 (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11440 }
11441
11442 maxAssertCPUDuration = 0;
11443 maxAssertCPUEntryId = 0;
11444 }
11445
11446 void
11447 PMAssertionsTracker::publishProperties( void )
11448 {
11449 OSSharedPtr<OSArray> assertionsSummary;
11450
11451 if (tabulateConsumerCount != tabulateProducerCount) {
11452 IOLockLock(assertionsArrayLock);
11453
11454 tabulateConsumerCount = tabulateProducerCount;
11455
11456 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11457 */
11458 assertionsSummary = copyAssertionsArray();
11459 if (assertionsSummary) {
11460 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11461 } else {
11462 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11463 }
11464
11465 /* Publish the IOPMrootDomain property "DriverPMAssertions"
11466 */
11467 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11468
11469 IOLockUnlock(assertionsArrayLock);
11470 }
11471 }
11472
11473 PMAssertStruct *
11474 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11475 {
11476 PMAssertStruct *_a = NULL;
11477 OSValueObject<PMAssertStruct> *_d = nullptr;
11478 int found = -1;
11479 int count = 0;
11480 int i = 0;
11481
11482 if (assertionsArray
11483 && (count = assertionsArray->getCount())) {
11484 for (i = 0; i < count; i++) {
11485 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11486 if (_d) {
11487 _a = _d->getMutableBytesNoCopy();
11488 if (_a && (_id == _a->id)) {
11489 found = i;
11490 break;
11491 }
11492 }
11493 }
11494 }
11495
11496 if (-1 == found) {
11497 return NULL;
11498 } else {
11499 if (index) {
11500 *index = found;
11501 }
11502 return _a;
11503 }
11504 }
11505
11506 /* PMAssertionsTracker::handleCreateAssertion
11507 * Perform assertion work on the PM workloop. Do not call directly.
11508 */
11509 IOReturn
11510 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11511 {
11512 PMAssertStruct *assertStruct = nullptr;
11513
11514 ASSERT_GATED();
11515
11516 if (newAssertion) {
11517 IOLockLock(assertionsArrayLock);
11518 assertStruct = newAssertion->getMutableBytesNoCopy();
11519 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11520 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11521 assertStruct->assertCPUStartTime = mach_absolute_time();
11522 }
11523 assertionsArray->setObject(newAssertion);
11524 IOLockUnlock(assertionsArrayLock);
11525 newAssertion->release();
11526
11527 tabulate();
11528 }
11529 return kIOReturnSuccess;
11530 }
11531
11532 /* PMAssertionsTracker::createAssertion
11533 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11534 * appropiate.
11535 */
11536 IOReturn
11537 PMAssertionsTracker::createAssertion(
11538 IOPMDriverAssertionType which,
11539 IOPMDriverAssertionLevel level,
11540 IOService *serviceID,
11541 const char *whoItIs,
11542 IOPMDriverAssertionID *outID)
11543 {
11544 OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11545 PMAssertStruct track;
11546
11547 // Warning: trillions and trillions of created assertions may overflow the unique ID.
11548 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11549 track.level = level;
11550 track.assertionBits = which;
11551
11552 // NB: ownerString is explicitly managed by PMAssertStruct
11553 // it will be released in `handleReleaseAssertion' below
11554 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11555 track.ownerService = serviceID;
11556 track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11557 track.modifiedTime = 0;
11558 pmEventTimeStamp(&track.createdTime);
11559 track.assertCPUStartTime = 0;
11560 track.assertCPUDuration = 0;
11561
11562 dataStore = OSValueObjectWithValue(track);
11563 if (!dataStore) {
11564 if (track.ownerString) {
11565 track.ownerString->release();
11566 track.ownerString = NULL;
11567 }
11568 return kIOReturnNoMemory;
11569 }
11570
11571 *outID = track.id;
11572
11573 if (owner && owner->pmPowerStateQueue) {
11574 // queue action is responsible for releasing dataStore
11575 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11576 }
11577
11578 return kIOReturnSuccess;
11579 }
11580
11581 /* PMAssertionsTracker::handleReleaseAssertion
11582 * Runs in PM workloop. Do not call directly.
11583 */
11584 IOReturn
11585 PMAssertionsTracker::handleReleaseAssertion(
11586 IOPMDriverAssertionID _id)
11587 {
11588 ASSERT_GATED();
11589
11590 int index;
11591 PMAssertStruct *assertStruct = detailsForID(_id, &index);
11592
11593 if (!assertStruct) {
11594 return kIOReturnNotFound;
11595 }
11596
11597 IOLockLock(assertionsArrayLock);
11598
11599 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11600 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11601 updateCPUBitAccounting(assertStruct);
11602 }
11603
11604 if (assertStruct->ownerString) {
11605 assertStruct->ownerString->release();
11606 assertStruct->ownerString = NULL;
11607 }
11608
11609 assertionsArray->removeObject(index);
11610 IOLockUnlock(assertionsArrayLock);
11611
11612 tabulate();
11613 return kIOReturnSuccess;
11614 }
11615
11616 /* PMAssertionsTracker::releaseAssertion
11617 * Releases an assertion and affects system behavior if appropiate.
11618 * Actual work happens on PM workloop.
11619 */
11620 IOReturn
11621 PMAssertionsTracker::releaseAssertion(
11622 IOPMDriverAssertionID _id)
11623 {
11624 if (owner && owner->pmPowerStateQueue) {
11625 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11626 }
11627 return kIOReturnSuccess;
11628 }
11629
11630 /* PMAssertionsTracker::handleSetAssertionLevel
11631 * Runs in PM workloop. Do not call directly.
11632 */
11633 IOReturn
11634 PMAssertionsTracker::handleSetAssertionLevel(
11635 IOPMDriverAssertionID _id,
11636 IOPMDriverAssertionLevel _level)
11637 {
11638 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
11639
11640 ASSERT_GATED();
11641
11642 if (!assertStruct) {
11643 return kIOReturnNotFound;
11644 }
11645
11646 IOLockLock(assertionsArrayLock);
11647 pmEventTimeStamp(&assertStruct->modifiedTime);
11648 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11649 (assertStruct->level != _level)) {
11650 if (_level == kIOPMDriverAssertionLevelOn) {
11651 assertStruct->assertCPUStartTime = mach_absolute_time();
11652 } else {
11653 updateCPUBitAccounting(assertStruct);
11654 }
11655 }
11656 assertStruct->level = _level;
11657 IOLockUnlock(assertionsArrayLock);
11658
11659 tabulate();
11660 return kIOReturnSuccess;
11661 }
11662
11663 /* PMAssertionsTracker::setAssertionLevel
11664 */
11665 IOReturn
11666 PMAssertionsTracker::setAssertionLevel(
11667 IOPMDriverAssertionID _id,
11668 IOPMDriverAssertionLevel _level)
11669 {
11670 if (owner && owner->pmPowerStateQueue) {
11671 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11672 (void *)(uintptr_t)_level, _id);
11673 }
11674
11675 return kIOReturnSuccess;
11676 }
11677
11678 IOReturn
11679 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11680 {
11681 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11682
11683 ASSERT_GATED();
11684
11685 if (new_user_levels != assertionsUser) {
11686 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11687 assertionsUser = new_user_levels;
11688 }
11689
11690 tabulate();
11691 return kIOReturnSuccess;
11692 }
11693
11694 IOReturn
11695 PMAssertionsTracker::setUserAssertionLevels(
11696 IOPMDriverAssertionType new_user_levels)
11697 {
11698 if (gIOPMWorkLoop) {
11699 gIOPMWorkLoop->runAction(
11700 OSMemberFunctionCast(
11701 IOWorkLoop::Action,
11702 this,
11703 &PMAssertionsTracker::handleSetUserAssertionLevels),
11704 this,
11705 (void *) &new_user_levels, NULL, NULL, NULL);
11706 }
11707
11708 return kIOReturnSuccess;
11709 }
11710
11711
11712 OSSharedPtr<OSArray>
11713 PMAssertionsTracker::copyAssertionsArray(void)
11714 {
11715 int count;
11716 int i;
11717 OSSharedPtr<OSArray> outArray = NULL;
11718
11719 if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11720 goto exit;
11721 }
11722 outArray = OSArray::withCapacity(count);
11723 if (!outArray) {
11724 goto exit;
11725 }
11726
11727 for (i = 0; i < count; i++) {
11728 const PMAssertStruct *_a = nullptr;
11729 OSValueObject<PMAssertStruct> *_d = nullptr;
11730 OSSharedPtr<OSDictionary> details;
11731
11732 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11733 if (_d && (_a = _d->getBytesNoCopy())) {
11734 OSSharedPtr<OSNumber> _n;
11735
11736 details = OSDictionary::withCapacity(7);
11737 if (!details) {
11738 continue;
11739 }
11740
11741 outArray->setObject(details.get());
11742
11743 _n = OSNumber::withNumber(_a->id, 64);
11744 if (_n) {
11745 details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11746 }
11747 _n = OSNumber::withNumber(_a->createdTime, 64);
11748 if (_n) {
11749 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11750 }
11751 _n = OSNumber::withNumber(_a->modifiedTime, 64);
11752 if (_n) {
11753 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11754 }
11755 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11756 if (_n) {
11757 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11758 }
11759 _n = OSNumber::withNumber(_a->level, 64);
11760 if (_n) {
11761 details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11762 }
11763 _n = OSNumber::withNumber(_a->assertionBits, 64);
11764 if (_n) {
11765 details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11766 }
11767
11768 if (_a->ownerString) {
11769 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11770 }
11771 }
11772 }
11773
11774 exit:
11775 return os::move(outArray);
11776 }
11777
11778 IOPMDriverAssertionType
11779 PMAssertionsTracker::getActivatedAssertions(void)
11780 {
11781 return assertionsCombined;
11782 }
11783
11784 IOPMDriverAssertionLevel
11785 PMAssertionsTracker::getAssertionLevel(
11786 IOPMDriverAssertionType type)
11787 {
11788 // FIXME: unused and also wrong
11789 if (type && ((type & assertionsKernel) == assertionsKernel)) {
11790 return kIOPMDriverAssertionLevelOn;
11791 } else {
11792 return kIOPMDriverAssertionLevelOff;
11793 }
11794 }
11795
11796 //*********************************************************************************
11797 //*********************************************************************************
11798 //*********************************************************************************
11799
11800
11801 static void
11802 pmEventTimeStamp(uint64_t *recordTS)
11803 {
11804 clock_sec_t tsec;
11805 clock_usec_t tusec;
11806
11807 if (!recordTS) {
11808 return;
11809 }
11810
11811 // We assume tsec fits into 32 bits; 32 bits holds enough
11812 // seconds for 136 years since the epoch in 1970.
11813 clock_get_calendar_microtime(&tsec, &tusec);
11814
11815
11816 // Pack the sec & microsec calendar time into a uint64_t, for fun.
11817 *recordTS = 0;
11818 *recordTS |= (uint32_t)tusec;
11819 *recordTS |= ((uint64_t)tsec << 32);
11820
11821 return;
11822 }
11823
11824 // MARK: -
11825 // MARK: IORootParent
11826
11827 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11828
11829 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11830
11831 // The reason that root domain needs a root parent is to facilitate demand
11832 // sleep, since a power change from the root parent cannot be vetoed.
11833 //
11834 // The above statement is no longer true since root domain now performs
11835 // demand sleep using overrides. But root parent remains to avoid changing
11836 // the power tree stacking. Root parent is parked at the max power state.
11837
11838
11839 static IOPMPowerState patriarchPowerStates[2] =
11840 {
11841 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11842 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11843 };
11844
11845 void
11846 IORootParent::initialize( void )
11847 {
11848
11849 gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
11850 gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
11851 gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
11852 gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
11853 gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
11854 gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
11855 gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
11856 gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
11857 gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
11858 gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
11859 gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
11860 gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
11861 gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
11862 gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
11863 gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
11864 gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
11865 gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
11866 gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
11867 gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
11868 gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
11869 gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
11870 gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
11871 gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
11872 gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
11873 gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
11874 gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
11875 gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
11876 gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
11877 gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
11878 gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
11879 gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
11880 gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
11881 gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
11882 gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
11883 gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
11884 gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
11885 gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
11886 gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
11887 gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
11888 gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
11889 gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
11890 gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
11891 gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
11892 gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
11893 }
11894
11895 bool
11896 IORootParent::start( IOService * nub )
11897 {
11898 IOService::start(nub);
11899 attachToParent( getRegistryRoot(), gIOPowerPlane );
11900 PMinit();
11901 registerPowerDriver(this, patriarchPowerStates, 2);
11902 makeUsable();
11903 return true;
11904 }
11905
11906 void
11907 IORootParent::shutDownSystem( void )
11908 {
11909 }
11910
11911 void
11912 IORootParent::restartSystem( void )
11913 {
11914 }
11915
11916 void
11917 IORootParent::sleepSystem( void )
11918 {
11919 }
11920
11921 void
11922 IORootParent::dozeSystem( void )
11923 {
11924 }
11925
11926 void
11927 IORootParent::sleepToDoze( void )
11928 {
11929 }
11930
11931 void
11932 IORootParent::wakeSystem( void )
11933 {
11934 }
11935
11936 OSSharedPtr<OSObject>
11937 IORootParent::copyProperty( const char * aKey) const
11938 {
11939 return IOService::copyProperty(aKey);
11940 }
11941
11942 uint32_t
11943 IOPMrootDomain::getWatchdogTimeout()
11944 {
11945 if (gSwdSleepWakeTimeout) {
11946 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11947 }
11948 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11949 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11950 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11951 } else {
11952 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11953 }
11954 }
11955
11956
11957 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11958 IOReturn
11959 IOPMrootDomain::restartWithStackshot()
11960 {
11961 takeStackshot(true);
11962
11963 return kIOReturnSuccess;
11964 }
11965
11966 void
11967 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
11968 {
11969 takeStackshot(wdogTrigger);
11970 }
11971
11972 void
11973 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
11974 {
11975 switch (tracePhase) {
11976 case kIOPMTracePointSleepStarted:
11977 *phaseString = "kIOPMTracePointSleepStarted";
11978 *description = "starting sleep";
11979 break;
11980
11981 case kIOPMTracePointSleepApplications:
11982 *phaseString = "kIOPMTracePointSleepApplications";
11983 *description = "notifying applications";
11984 break;
11985
11986 case kIOPMTracePointSleepPriorityClients:
11987 *phaseString = "kIOPMTracePointSleepPriorityClients";
11988 *description = "notifying clients about upcoming system capability changes";
11989 break;
11990
11991 case kIOPMTracePointSleepWillChangeInterests:
11992 *phaseString = "kIOPMTracePointSleepWillChangeInterests";
11993 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11994 break;
11995
11996 case kIOPMTracePointSleepPowerPlaneDrivers:
11997 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
11998 *description = "calling power state change callbacks";
11999 break;
12000
12001 case kIOPMTracePointSleepDidChangeInterests:
12002 *phaseString = "kIOPMTracePointSleepDidChangeInterests";
12003 *description = "calling rootDomain's clients about rootDomain's state changes";
12004 break;
12005
12006 case kIOPMTracePointSleepCapabilityClients:
12007 *phaseString = "kIOPMTracePointSleepCapabilityClients";
12008 *description = "notifying clients about current system capabilities";
12009 break;
12010
12011 case kIOPMTracePointSleepPlatformActions:
12012 *phaseString = "kIOPMTracePointSleepPlatformActions";
12013 *description = "calling Quiesce/Sleep action callbacks";
12014 break;
12015
12016 case kIOPMTracePointSleepCPUs:
12017 {
12018 *phaseString = "kIOPMTracePointSleepCPUs";
12019 #if defined(__i386__) || defined(__x86_64__)
12020 /*
12021 * We cannot use the getCPUNumber() method to get the cpu number, since
12022 * that cpu number is unrelated to the cpu number we need (we need the cpu
12023 * number as enumerated by the scheduler, NOT the CPU number enumerated
12024 * by ACPIPlatform as the CPUs are enumerated in MADT order).
12025 * Instead, pass the Mach processor pointer associated with the current
12026 * shutdown target so its associated cpu_id can be used in
12027 * processor_to_datastring.
12028 */
12029 if (currentShutdownTarget != NULL &&
12030 currentShutdownTarget->getMachProcessor() != NULL) {
12031 const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
12032 currentShutdownTarget->getMachProcessor());
12033 *description = sbuf;
12034 } else {
12035 *description = "halting all non-boot CPUs";
12036 }
12037 #else
12038 *description = "halting all non-boot CPUs";
12039 #endif
12040 break;
12041 }
12042 case kIOPMTracePointSleepPlatformDriver:
12043 *phaseString = "kIOPMTracePointSleepPlatformDriver";
12044 *description = "executing platform specific code";
12045 break;
12046
12047 case kIOPMTracePointHibernate:
12048 *phaseString = "kIOPMTracePointHibernate";
12049 *description = "writing the hibernation image";
12050 break;
12051
12052 case kIOPMTracePointSystemSleep:
12053 *phaseString = "kIOPMTracePointSystemSleep";
12054 *description = "in EFI/Bootrom after last point of entry to sleep";
12055 break;
12056
12057 case kIOPMTracePointWakePlatformDriver:
12058 *phaseString = "kIOPMTracePointWakePlatformDriver";
12059 *description = "executing platform specific code";
12060 break;
12061
12062
12063 case kIOPMTracePointWakePlatformActions:
12064 *phaseString = "kIOPMTracePointWakePlatformActions";
12065 *description = "calling Wake action callbacks";
12066 break;
12067
12068 case kIOPMTracePointWakeCPUs:
12069 *phaseString = "kIOPMTracePointWakeCPUs";
12070 *description = "starting non-boot CPUs";
12071 break;
12072
12073 case kIOPMTracePointWakeWillPowerOnClients:
12074 *phaseString = "kIOPMTracePointWakeWillPowerOnClients";
12075 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
12076 break;
12077
12078 case kIOPMTracePointWakeWillChangeInterests:
12079 *phaseString = "kIOPMTracePointWakeWillChangeInterests";
12080 *description = "calling rootDomain's clients about upcoming rootDomain's state changes";
12081 break;
12082
12083 case kIOPMTracePointWakeDidChangeInterests:
12084 *phaseString = "kIOPMTracePointWakeDidChangeInterests";
12085 *description = "calling rootDomain's clients about completed rootDomain's state changes";
12086 break;
12087
12088 case kIOPMTracePointWakePowerPlaneDrivers:
12089 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
12090 *description = "calling power state change callbacks";
12091 break;
12092
12093 case kIOPMTracePointWakeCapabilityClients:
12094 *phaseString = "kIOPMTracePointWakeCapabilityClients";
12095 *description = "informing clients about current system capabilities";
12096 break;
12097
12098 case kIOPMTracePointWakeApplications:
12099 *phaseString = "kIOPMTracePointWakeApplications";
12100 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
12101 break;
12102
12103 case kIOPMTracePointDarkWakeEntry:
12104 *phaseString = "kIOPMTracePointDarkWakeEntry";
12105 *description = "entering darkwake on way to sleep";
12106 break;
12107
12108 case kIOPMTracePointDarkWakeExit:
12109 *phaseString = "kIOPMTracePointDarkWakeExit";
12110 *description = "entering fullwake from darkwake";
12111 break;
12112
12113 default:
12114 *phaseString = NULL;
12115 *description = NULL;
12116 }
12117 }
12118
12119 void
12120 IOPMrootDomain::saveFailureData2File()
12121 {
12122 unsigned int len = 0;
12123 char failureStr[512];
12124 errno_t error;
12125 char *outbuf;
12126 OSNumber *statusCode;
12127 uint64_t pmStatusCode = 0;
12128 uint32_t phaseData = 0;
12129 uint32_t phaseDetail = 0;
12130 bool efiFailure = false;
12131
12132 OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
12133 statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
12134 if (statusCode) {
12135 pmStatusCode = statusCode->unsigned64BitValue();
12136 phaseData = pmStatusCode & 0xFFFFFFFF;
12137 phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
12138 if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
12139 LOG("Sleep Wake failure in EFI\n");
12140 efiFailure = true;
12141 failureStr[0] = 0;
12142 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);
12143 len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12144 }
12145 }
12146
12147 if (!efiFailure) {
12148 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12149 swd_flags |= SWD_BOOT_BY_SW_WDOG;
12150 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12151 // dump panic will handle saving nvram data
12152 return;
12153 }
12154
12155 /* Keeping this around for capturing data during power
12156 * button press */
12157
12158 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12159 DLOG("No sleep wake failure string\n");
12160 return;
12161 }
12162 if (len == 0) {
12163 DLOG("Ignoring zero byte SleepWake failure string\n");
12164 goto exit;
12165 }
12166
12167 // if PMStatus code is zero, delete stackshot and return
12168 if (statusCode) {
12169 if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12170 // there was no sleep wake failure
12171 // this can happen if delete stackshot was called
12172 // before take stackshot completed. Let us delete any
12173 // sleep wake failure data in nvram
12174 DLOG("Deleting stackshot on successful wake\n");
12175 deleteStackshot();
12176 return;
12177 }
12178 }
12179
12180 if (len > sizeof(failureStr)) {
12181 len = sizeof(failureStr);
12182 }
12183 failureStr[0] = 0;
12184 PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12185 }
12186 if (failureStr[0] != 0) {
12187 error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12188 if (error) {
12189 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12190 } else {
12191 DLOG("Saved SleepWake failure string to file.\n");
12192 }
12193 }
12194
12195 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12196 goto exit;
12197 }
12198
12199 if (swd_buffer) {
12200 unsigned int len = 0;
12201 errno_t error;
12202 char nvram_var_name_buffer[20];
12203 unsigned int concat_len = 0;
12204 swd_hdr *hdr = NULL;
12205
12206
12207 hdr = (swd_hdr *)swd_buffer;
12208 outbuf = (char *)hdr + hdr->spindump_offset;
12209 OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12210
12211 for (int i = 0; i < 8; i++) {
12212 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12213 if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12214 LOG("No SleepWake blob to read beyond chunk %d\n", i);
12215 break;
12216 }
12217 if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12218 PERemoveNVRAMProperty(nvram_var_name_buffer);
12219 LOG("Could not read the property :-(\n");
12220 break;
12221 }
12222 PERemoveNVRAMProperty(nvram_var_name_buffer);
12223 concat_len += len;
12224 }
12225 LOG("Concatenated length for the SWD blob %d\n", concat_len);
12226
12227 if (concat_len) {
12228 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12229 if (error) {
12230 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12231 } else {
12232 LOG("Saved SleepWake zipped data to file.\n");
12233 }
12234 } else {
12235 // There is a sleep wake failure string but no stackshot
12236 // Write a placeholder stacks file so that swd runs
12237 snprintf(outbuf, 20, "%s", "No stackshot data\n");
12238 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12239 if (error) {
12240 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12241 } else {
12242 LOG("Saved SleepWake zipped data to file.\n");
12243 }
12244 }
12245 } else {
12246 LOG("No buffer allocated to save failure stackshot\n");
12247 }
12248
12249
12250 gRootDomain->swd_lock = 0;
12251 exit:
12252 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12253 return;
12254 }
12255
12256
12257 void
12258 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12259 {
12260 OSSharedPtr<IORegistryIterator> iter;
12261 OSSharedPtr<const OSSymbol> kextName = NULL;
12262 IORegistryEntry * entry;
12263 IOService * node;
12264 bool nodeFound = false;
12265
12266 const void * callMethod = NULL;
12267 const char * objectName = NULL;
12268 const char * phaseString = NULL;
12269 const char * phaseDescription = NULL;
12270 uint64_t delta;
12271
12272 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12273 uint32_t tracePhase = pmTracer->getTracePhase();
12274
12275 *thread = NULL;
12276
12277 delta = get_watchdog_elapsed_time();
12278 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12279 snprintf(failureStr, strLen, "Sleep transition timed out after %qd seconds", delta);
12280 } else {
12281 snprintf(failureStr, strLen, "Wake transition timed out after %qd seconds", delta);
12282 }
12283 tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12284
12285 if (notifierThread) {
12286 if (notifier && (notifier->identifier)) {
12287 objectName = notifier->identifier->getCStringNoCopy();
12288 }
12289 *thread = notifierThread;
12290 } else {
12291 iter = IORegistryIterator::iterateOver(
12292 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12293
12294 if (iter) {
12295 while ((entry = iter->getNextObject())) {
12296 node = OSDynamicCast(IOService, entry);
12297 if (!node) {
12298 continue;
12299 }
12300 if (OSDynamicCast(IOPowerConnection, node)) {
12301 continue;
12302 }
12303
12304 if (node->getBlockingDriverCall(thread, &callMethod)) {
12305 nodeFound = true;
12306 break;
12307 }
12308 }
12309 }
12310 if (nodeFound) {
12311 kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12312 if (kextName) {
12313 objectName = kextName->getCStringNoCopy();
12314 }
12315 }
12316 }
12317 if (phaseDescription) {
12318 strlcat(failureStr, " while ", strLen);
12319 strlcat(failureStr, phaseDescription, strLen);
12320 strlcat(failureStr, ".", strLen);
12321 }
12322 if (objectName) {
12323 strlcat(failureStr, " Suspected bundle: ", strLen);
12324 strlcat(failureStr, objectName, strLen);
12325 strlcat(failureStr, ".", strLen);
12326 }
12327 if (*thread) {
12328 char threadName[40];
12329 snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12330 strlcat(failureStr, threadName, strLen);
12331 }
12332
12333 DLOG("%s\n", failureStr);
12334 }
12335
12336 struct swd_stackshot_compressed_data {
12337 z_output_func zoutput;
12338 size_t zipped;
12339 uint64_t totalbytes;
12340 uint64_t lastpercent;
12341 IOReturn error;
12342 unsigned outremain;
12343 unsigned outlen;
12344 unsigned writes;
12345 Bytef * outbuf;
12346 };
12347 struct swd_stackshot_compressed_data swd_zip_var = { };
12348
12349 static void *
12350 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12351 {
12352 void *result;
12353 LOG("Alloc in zipping %d items of size %d\n", items, size);
12354
12355 result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12356 swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12357 LOG("Offset %zu\n", swd_zs_zoffset);
12358 return result;
12359 }
12360
12361 static int
12362 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12363 {
12364 unsigned len;
12365
12366 len = strm->avail_in;
12367
12368 if (len > size) {
12369 len = size;
12370 }
12371 if (len == 0) {
12372 return 0;
12373 }
12374
12375 if (strm->next_in != (Bytef *) strm) {
12376 memcpy(buf, strm->next_in, len);
12377 } else {
12378 bzero(buf, len);
12379 }
12380
12381 strm->adler = z_crc32(strm->adler, buf, len);
12382
12383 strm->avail_in -= len;
12384 strm->next_in += len;
12385 strm->total_in += len;
12386
12387 return (int)len;
12388 }
12389
12390 static int
12391 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12392 {
12393 unsigned int i = 0;
12394 // if outlen > max size don't add to the buffer
12395 assert(buf != NULL);
12396 if (strm && buf) {
12397 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12398 LOG("No space to GZIP... not writing to NVRAM\n");
12399 return len;
12400 }
12401 }
12402 for (i = 0; i < len; i++) {
12403 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12404 }
12405 swd_zip_var.outlen += len;
12406 return len;
12407 }
12408
12409 static void
12410 swd_zs_free(void * __unused ref, void * __unused ptr)
12411 {
12412 }
12413
12414 static int
12415 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12416 {
12417 int wbits = 12;
12418 int memlevel = 3;
12419
12420 if (((unsigned int) numBytes) != numBytes) {
12421 return 0;
12422 }
12423
12424 if (!swd_zs.zalloc) {
12425 swd_zs.zalloc = swd_zs_alloc;
12426 swd_zs.zfree = swd_zs_free;
12427 if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12428 // allocation failed
12429 bzero(&swd_zs, sizeof(swd_zs));
12430 // swd_zs_zoffset = 0;
12431 } else {
12432 LOG("PMRD inited the zlib allocation routines\n");
12433 }
12434 }
12435
12436 swd_zip_var.zipped = 0;
12437 swd_zip_var.totalbytes = 0; // should this be the max that we have?
12438 swd_zip_var.lastpercent = 0;
12439 swd_zip_var.error = kIOReturnSuccess;
12440 swd_zip_var.outremain = 0;
12441 swd_zip_var.outlen = 0;
12442 swd_zip_var.writes = 0;
12443 swd_zip_var.outbuf = (Bytef *)outPtr;
12444
12445 swd_zip_var.totalbytes = numBytes;
12446
12447 swd_zs.avail_in = 0;
12448 swd_zs.next_in = NULL;
12449 swd_zs.avail_out = 0;
12450 swd_zs.next_out = NULL;
12451
12452 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12453
12454 z_stream *zs;
12455 int zr;
12456 zs = &swd_zs;
12457
12458 while (swd_zip_var.error >= 0) {
12459 if (!zs->avail_in) {
12460 zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12461 zs->avail_in = (unsigned int) numBytes;
12462 }
12463 if (!zs->avail_out) {
12464 zs->next_out = (Bytef *)zs;
12465 zs->avail_out = UINT32_MAX;
12466 }
12467 zr = deflate(zs, Z_NO_FLUSH);
12468 if (Z_STREAM_END == zr) {
12469 break;
12470 }
12471 if (zr != Z_OK) {
12472 LOG("ZERR %d\n", zr);
12473 swd_zip_var.error = zr;
12474 } else {
12475 if (zs->total_in == numBytes) {
12476 break;
12477 }
12478 }
12479 }
12480
12481 //now flush the stream
12482 while (swd_zip_var.error >= 0) {
12483 if (!zs->avail_out) {
12484 zs->next_out = (Bytef *)zs;
12485 zs->avail_out = UINT32_MAX;
12486 }
12487 zr = deflate(zs, Z_FINISH);
12488 if (Z_STREAM_END == zr) {
12489 break;
12490 }
12491 if (zr != Z_OK) {
12492 LOG("ZERR %d\n", zr);
12493 swd_zip_var.error = zr;
12494 } else {
12495 if (zs->total_in == numBytes) {
12496 LOG("Total output size %d\n", swd_zip_var.outlen);
12497 break;
12498 }
12499 }
12500 }
12501
12502 return swd_zip_var.outlen;
12503 }
12504
12505 void
12506 IOPMrootDomain::deleteStackshot()
12507 {
12508 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12509 // takeStackshot hasn't completed
12510 return;
12511 }
12512 LOG("Deleting any sleepwake failure data in nvram\n");
12513
12514 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12515 char nvram_var_name_buf[20];
12516 for (int i = 0; i < 8; i++) {
12517 snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12518 if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12519 LOG("Removing %s returned false\n", nvram_var_name_buf);
12520 }
12521 }
12522 // force NVRAM sync
12523 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12524 DLOG("Failed to force nvram sync\n");
12525 }
12526 gRootDomain->swd_lock = 0;
12527 }
12528
12529 void
12530 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12531 {
12532 swd_hdr * hdr = NULL;
12533 int cnt = 0;
12534 int max_cnt;
12535 pid_t pid = 0;
12536 kern_return_t kr = KERN_SUCCESS;
12537 uint64_t flags;
12538
12539 char * dstAddr;
12540 uint32_t size;
12541 uint32_t bytesRemaining;
12542 unsigned bytesWritten = 0;
12543
12544 char failureStr[512];
12545 thread_t thread = NULL;
12546 const char * swfPanic = "swfPanic";
12547
12548 uint32_t bufSize;
12549 int success = 0;
12550
12551 #if defined(__i386__) || defined(__x86_64__)
12552 const bool concise = false;
12553 #else
12554 const bool concise = true;
12555 #endif
12556
12557 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12558 return;
12559 }
12560
12561 failureStr[0] = 0;
12562 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12563 return;
12564 }
12565
12566 if (wdogTrigger) {
12567 getFailureData(&thread, failureStr, sizeof(failureStr));
12568
12569 if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12570 goto skip_stackshot;
12571 }
12572 } else {
12573 AbsoluteTime now;
12574 uint64_t nsec;
12575 clock_get_uptime(&now);
12576 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12577 absolutetime_to_nanoseconds(now, &nsec);
12578 snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12579 }
12580
12581 if (swd_buffer == NULL) {
12582 sleepWakeDebugMemAlloc();
12583 if (swd_buffer == NULL) {
12584 return;
12585 }
12586 }
12587 hdr = (swd_hdr *)swd_buffer;
12588 bufSize = hdr->alloc_size;
12589
12590 dstAddr = (char*)hdr + hdr->spindump_offset;
12591 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;
12592
12593 /* If not wdogTrigger only take kernel tasks stackshot
12594 */
12595 if (wdogTrigger) {
12596 pid = -1;
12597 max_cnt = 3;
12598 } else {
12599 pid = 0;
12600 max_cnt = 2;
12601 }
12602
12603 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12604 * If we run out of space, take stackshot with only kernel task
12605 */
12606 while (success == 0 && cnt < max_cnt) {
12607 bytesRemaining = bufSize - hdr->spindump_offset;
12608 cnt++;
12609 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12610
12611 size = bytesRemaining;
12612 kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12613 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12614 kr, pid, size, flags, bytesWritten);
12615 if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12616 if (pid == -1) {
12617 pid = 0;
12618 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12619 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12620 } else {
12621 LOG("Insufficient buffer size for only kernel task\n");
12622 break;
12623 }
12624 }
12625 if (kr == KERN_SUCCESS) {
12626 if (bytesWritten == 0) {
12627 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12628 continue;
12629 }
12630 bytesRemaining -= bytesWritten;
12631 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12632
12633 memset(hdr->reason, 0x20, sizeof(hdr->reason));
12634
12635 // Compress stackshot and save to NVRAM
12636 {
12637 char *outbuf = (char *)swd_compressed_buffer;
12638 int outlen = 0;
12639 int num_chunks = 0;
12640 int max_chunks = 0;
12641 int leftover = 0;
12642 char nvram_var_name_buffer[20];
12643
12644 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12645
12646 if (outlen) {
12647 max_chunks = outlen / (2096 - 200);
12648 leftover = outlen % (2096 - 200);
12649
12650 if (max_chunks < 8) {
12651 for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
12652 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12653 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
12654 LOG("Failed to update NVRAM %d\n", num_chunks);
12655 break;
12656 }
12657 }
12658 if (leftover) {
12659 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12660 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
12661 LOG("Failed to update NVRAM with leftovers\n");
12662 }
12663 }
12664 success = 1;
12665 LOG("Successfully saved stackshot to NVRAM\n");
12666 } else {
12667 if (pid == -1) {
12668 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12669 pid = 0;
12670 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12671 LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
12672 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12673 } else {
12674 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12675 break;
12676 }
12677 }
12678 }
12679 }
12680 }
12681 }
12682
12683 if (failureStr[0]) {
12684 // append sleep-wake failure code
12685 char traceCode[80];
12686 snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
12687 pmTracer->getTraceData(), pmTracer->getTracePhase());
12688 strlcat(failureStr, traceCode, sizeof(failureStr));
12689 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
12690 DLOG("Failed to write SleepWake failure string\n");
12691 }
12692 }
12693
12694 // force NVRAM sync
12695 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12696 DLOG("Failed to force nvram sync\n");
12697 }
12698
12699 skip_stackshot:
12700 if (wdogTrigger) {
12701 if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
12702 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
12703 // If current boot is due to this watch dog trigger restart in previous boot,
12704 // then don't trigger again until at least 1 successful sleep & wake.
12705 if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
12706 LOG("Shutting down due to repeated Sleep/Wake failures\n");
12707 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12708 PEHaltRestart(kPEHaltCPU);
12709 return;
12710 }
12711 }
12712 if (gSwdPanic == 0) {
12713 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12714 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12715 PEHaltRestart(kPERestartCPU);
12716 }
12717 }
12718 if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12719 DLOG("Failed to write SleepWake failure panic key\n");
12720 }
12721 #if defined(__x86_64__)
12722 if (thread) {
12723 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12724 } else
12725 #endif /* defined(__x86_64__) */
12726 {
12727 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12728 }
12729 } else {
12730 gRootDomain->swd_lock = 0;
12731 return;
12732 }
12733 }
12734
12735 void
12736 IOPMrootDomain::sleepWakeDebugMemAlloc()
12737 {
12738 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12739
12740 swd_hdr *hdr = NULL;
12741 void *bufPtr = NULL;
12742
12743 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12744
12745
12746 if (kIOSleepWakeWdogOff & gIOKitDebug) {
12747 return;
12748 }
12749
12750 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12751 return;
12752 }
12753
12754 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12755 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12756 size);
12757 if (memDesc == NULL) {
12758 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12759 goto exit;
12760 }
12761
12762 bufPtr = memDesc->getBytesNoCopy();
12763
12764 // Carve out memory for zlib routines
12765 swd_zs_zmem = (vm_offset_t)bufPtr;
12766 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12767
12768 // Carve out memory for compressed stackshots
12769 swd_compressed_buffer = bufPtr;
12770 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12771
12772 // Remaining is used for holding stackshot
12773 hdr = (swd_hdr *)bufPtr;
12774 memset(hdr, 0, sizeof(swd_hdr));
12775
12776 hdr->signature = SWD_HDR_SIGNATURE;
12777 hdr->alloc_size = SWD_STACKSHOT_SIZE;
12778
12779 hdr->spindump_offset = sizeof(swd_hdr);
12780 swd_buffer = (void *)hdr;
12781 swd_memDesc = os::move(memDesc);
12782 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
12783
12784 exit:
12785 gRootDomain->swd_lock = 0;
12786 }
12787
12788 void
12789 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12790 {
12791 #if UNUSED
12792 vm_size_t size = SWD_SPINDUMP_SIZE;
12793
12794 swd_hdr *hdr = NULL;
12795
12796 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12797
12798 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12799 return;
12800 }
12801
12802 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12803 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12804 SWD_SPINDUMP_SIZE);
12805
12806 if (memDesc == NULL) {
12807 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12808 goto exit;
12809 }
12810
12811
12812 hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12813 memset(hdr, 0, sizeof(swd_hdr));
12814
12815 hdr->signature = SWD_HDR_SIGNATURE;
12816 hdr->alloc_size = size;
12817
12818 hdr->spindump_offset = sizeof(swd_hdr);
12819 swd_spindump_buffer = (void *)hdr;
12820 swd_spindump_memDesc = os::move(memDesc);
12821
12822 exit:
12823 gRootDomain->swd_lock = 0;
12824 #endif /* UNUSED */
12825 }
12826
12827 void
12828 IOPMrootDomain::sleepWakeDebugEnableWdog()
12829 {
12830 }
12831
12832 bool
12833 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12834 {
12835 return !systemBooting && !systemShutdown && !gWillShutdown;
12836 }
12837
12838 void
12839 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12840 {
12841 swd_hdr *hdr = NULL;
12842 errno_t error = EIO;
12843
12844 if (swd_spindump_buffer && gSpinDumpBufferFull) {
12845 hdr = (swd_hdr *)swd_spindump_buffer;
12846
12847 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12848 (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12849
12850 if (error) {
12851 return;
12852 }
12853
12854 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12855 (char*)hdr + offsetof(swd_hdr, UUID),
12856 sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12857
12858 gSpinDumpBufferFull = false;
12859 }
12860 }
12861
12862 errno_t
12863 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12864 {
12865 struct vnode *vp = NULL;
12866 vfs_context_t ctx = vfs_context_create(vfs_context_current());
12867 kauth_cred_t cred = vfs_context_ucred(ctx);
12868 struct vnode_attr va;
12869 errno_t error = EIO;
12870
12871 if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
12872 S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
12873 LOG("Failed to open the file %s\n", name);
12874 swd_flags |= SWD_FILEOP_ERROR;
12875 goto exit;
12876 }
12877 VATTR_INIT(&va);
12878 VATTR_WANTED(&va, va_nlink);
12879 /* Don't dump to non-regular files or files with links. */
12880 if (vp->v_type != VREG ||
12881 vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
12882 LOG("Bailing as this is not a regular file\n");
12883 swd_flags |= SWD_FILEOP_ERROR;
12884 goto exit;
12885 }
12886 VATTR_INIT(&va);
12887 VATTR_SET(&va, va_data_size, 0);
12888 vnode_setattr(vp, &va, ctx);
12889
12890
12891 if (buf != NULL) {
12892 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12893 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12894 if (error != 0) {
12895 LOG("Failed to save sleep wake log. err 0x%x\n", error);
12896 swd_flags |= SWD_FILEOP_ERROR;
12897 } else {
12898 DLOG("Saved %d bytes to file %s\n", len, name);
12899 }
12900 }
12901
12902 exit:
12903 if (vp) {
12904 vnode_close(vp, FWRITE, ctx);
12905 }
12906 if (ctx) {
12907 vfs_context_rele(ctx);
12908 }
12909
12910 return error;
12911 }
12912
12913 #else /* defined(__i386__) || defined(__x86_64__) */
12914
12915 void
12916 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12917 {
12918 if (restart) {
12919 if (gSwdPanic == 0) {
12920 return;
12921 }
12922 panic("Sleep/Wake hang detected");
12923 return;
12924 }
12925 }
12926
12927 void
12928 IOPMrootDomain::takeStackshot(bool restart)
12929 {
12930 #pragma unused(restart)
12931 }
12932
12933 void
12934 IOPMrootDomain::deleteStackshot()
12935 {
12936 }
12937
12938 void
12939 IOPMrootDomain::sleepWakeDebugMemAlloc()
12940 {
12941 }
12942
12943 void
12944 IOPMrootDomain::saveFailureData2File()
12945 {
12946 }
12947
12948 void
12949 IOPMrootDomain::sleepWakeDebugEnableWdog()
12950 {
12951 }
12952
12953 bool
12954 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12955 {
12956 return false;
12957 }
12958
12959 void
12960 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12961 {
12962 }
12963
12964 errno_t
12965 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12966 {
12967 return 0;
12968 }
12969
12970 #endif /* defined(__i386__) || defined(__x86_64__) */
12971
12972