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