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