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