1 /*
2 * Copyright (c) 1998-2021 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #define IOKIT_ENABLE_SHARED_PTR
30
31 #include <libkern/c++/OSAllocation.h>
32 #include <libkern/c++/OSKext.h>
33 #include <libkern/c++/OSMetaClass.h>
34 #include <libkern/OSAtomic.h>
35 #include <libkern/OSDebug.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommandGate.h>
38 #include <IOKit/IOTimerEventSource.h>
39 #include <IOKit/IOPlatformExpert.h>
40 #include <IOKit/IOCPU.h>
41 #include <IOKit/IOPlatformActions.h>
42 #include <IOKit/IOKitDebug.h>
43 #include <IOKit/IOTimeStamp.h>
44 #include <IOKit/pwr_mgt/IOPMlog.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
46 #include <IOKit/pwr_mgt/IOPMPrivate.h>
47 #include <IOKit/IODeviceTreeSupport.h>
48 #include <IOKit/IOMessage.h>
49 #include <IOKit/IOReturn.h>
50 #include <IOKit/IONVRAM.h>
51 #include "RootDomainUserClient.h"
52 #include "IOKit/pwr_mgt/IOPowerConnection.h"
53 #include "IOPMPowerStateQueue.h"
54 #include <IOKit/IOCatalogue.h>
55 #include <IOKit/IOReportMacros.h>
56 #include <IOKit/IOLib.h>
57 #include <IOKit/IOKitKeys.h>
58 #include <IOKit/IOUserServer.h>
59 #include "IOKitKernelInternal.h"
60 #if HIBERNATION
61 #include <IOKit/IOHibernatePrivate.h>
62 #endif /* HIBERNATION */
63 #include <console/video_console.h>
64 #include <sys/syslog.h>
65 #include <sys/sysctl.h>
66 #include <sys/vnode.h>
67 #include <sys/vnode_internal.h>
68 #include <sys/fcntl.h>
69 #include <os/log.h>
70 #include <pexpert/protos.h>
71 #include <AssertMacros.h>
72
73 #include <sys/time.h>
74 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
75 #include "IOServicePMPrivate.h"
76
77 #include <libkern/zlib.h>
78 #include <os/cpp_util.h>
79 #include <os/atomic_private.h>
80 #include <libkern/c++/OSBoundedArrayRef.h>
81
82 #if DEVELOPMENT || DEBUG
83 #include <os/system_event_log.h>
84 #endif /* DEVELOPMENT || DEBUG */
85
86 __BEGIN_DECLS
87 #include <mach/shared_region.h>
88 #include <kern/clock.h>
89 __END_DECLS
90
91 #if defined(__i386__) || defined(__x86_64__)
92 __BEGIN_DECLS
93 #include "IOPMrootDomainInternal.h"
94 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
95 __END_DECLS
96 #endif
97
98 #define kIOPMrootDomainClass "IOPMrootDomain"
99 #define LOG_PREFIX "PMRD: "
100
101
102 #define MSG(x...) \
103 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
104
105 #define LOG(x...) \
106 do { kprintf(LOG_PREFIX x); } while (false)
107
108 #if DEVELOPMENT || DEBUG
109 #define DEBUG_LOG(x...) do { \
110 if (kIOLogPMRootDomain & gIOKitDebug) \
111 kprintf(LOG_PREFIX x); \
112 os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
113 } while (false)
114 #else
115 #define DEBUG_LOG(x...)
116 #endif
117
118 #define DLOG(x...) do { \
119 if (kIOLogPMRootDomain & gIOKitDebug) \
120 IOLog(LOG_PREFIX x); \
121 else \
122 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
123 } while (false)
124
125 #define DMSG(x...) do { \
126 if (kIOLogPMRootDomain & gIOKitDebug) { \
127 kprintf(LOG_PREFIX x); \
128 } \
129 } while (false)
130
131
132 #define _LOG(x...)
133
134 #define CHECK_THREAD_CONTEXT
135 #ifdef CHECK_THREAD_CONTEXT
136 static IOWorkLoop * gIOPMWorkLoop = NULL;
137 #define ASSERT_GATED() \
138 do { \
139 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
140 panic("RootDomain: not inside PM gate"); \
141 } \
142 } while(false)
143 #else
144 #define ASSERT_GATED()
145 #endif /* CHECK_THREAD_CONTEXT */
146
147 #define CAP_LOSS(c) \
148 (((_pendingCapability & (c)) == 0) && \
149 ((_currentCapability & (c)) != 0))
150
151 #define CAP_GAIN(c) \
152 (((_currentCapability & (c)) == 0) && \
153 ((_pendingCapability & (c)) != 0))
154
155 #define CAP_CHANGE(c) \
156 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
157
158 #define CAP_CURRENT(c) \
159 ((_currentCapability & (c)) != 0)
160
161 #define CAP_HIGHEST(c) \
162 ((_highestCapability & (c)) != 0)
163
164 #define CAP_PENDING(c) \
165 ((_pendingCapability & (c)) != 0)
166
167 // rdar://problem/9157444
168 #if defined(__i386__) || defined(__x86_64__)
169 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 20
170 #endif
171
172 // Event types for IOPMPowerStateQueue::submitPowerEvent()
173 enum {
174 kPowerEventFeatureChanged = 1, // 1
175 kPowerEventReceivedPowerNotification, // 2
176 kPowerEventSystemBootCompleted, // 3
177 kPowerEventSystemShutdown, // 4
178 kPowerEventUserDisabledSleep, // 5
179 kPowerEventRegisterSystemCapabilityClient, // 6
180 kPowerEventRegisterKernelCapabilityClient, // 7
181 kPowerEventPolicyStimulus, // 8
182 kPowerEventAssertionCreate, // 9
183 kPowerEventAssertionRelease, // 10
184 kPowerEventAssertionSetLevel, // 11
185 kPowerEventQueueSleepWakeUUID, // 12
186 kPowerEventPublishSleepWakeUUID, // 13
187 kPowerEventSetDisplayPowerOn, // 14
188 kPowerEventPublishWakeType, // 15
189 kPowerEventAOTEvaluate // 16
190 };
191
192 // For evaluatePolicy()
193 // List of stimuli that affects the root domain policy.
194 enum {
195 kStimulusDisplayWranglerSleep, // 0
196 kStimulusDisplayWranglerWake, // 1
197 kStimulusAggressivenessChanged, // 2
198 kStimulusDemandSystemSleep, // 3
199 kStimulusAllowSystemSleepChanged, // 4
200 kStimulusDarkWakeActivityTickle, // 5
201 kStimulusDarkWakeEntry, // 6
202 kStimulusDarkWakeReentry, // 7
203 kStimulusDarkWakeEvaluate, // 8
204 kStimulusNoIdleSleepPreventers, // 9
205 kStimulusEnterUserActiveState, // 10
206 kStimulusLeaveUserActiveState // 11
207 };
208
209 // Internal power state change reasons
210 // Must be less than kIOPMSleepReasonClamshell=101
211 enum {
212 kCPSReasonNone = 0, // 0
213 kCPSReasonInit, // 1
214 kCPSReasonWake, // 2
215 kCPSReasonIdleSleepPrevent, // 3
216 kCPSReasonIdleSleepAllow, // 4
217 kCPSReasonPowerOverride, // 5
218 kCPSReasonPowerDownCancel, // 6
219 kCPSReasonAOTExit, // 7
220 kCPSReasonAdjustPowerState, // 8
221 kCPSReasonDarkWakeCannotSleep, // 9
222 kCPSReasonIdleSleepEnabled, // 10
223 kCPSReasonEvaluatePolicy, // 11
224 kCPSReasonSustainFullWake, // 12
225 kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1)
226 };
227
228 extern "C" {
229 IOReturn OSKextSystemSleepOrWake( UInt32 );
230 }
231 extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
232 extern "C" addr64_t kvtophys(vm_offset_t va);
233 extern "C" boolean_t kdp_has_polled_corefile();
234
235 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
236 static void notifySystemShutdown( IOService * root, uint32_t messageType );
237 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
238 static void pmEventTimeStamp(uint64_t *recordTS);
239 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
240 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
241 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address);
242
243 static int IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt);
244 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
245 #define YMDTF "%04d/%02d/%d %02d:%02d:%02d"
246 #define YMDT(cal) ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
247
248 // "IOPMSetSleepSupported" callPlatformFunction name
249 static OSSharedPtr<const OSSymbol> sleepSupportedPEFunction;
250 static OSSharedPtr<const OSSymbol> sleepMessagePEFunction;
251 static OSSharedPtr<const OSSymbol> gIOPMWakeTypeUserKey;
252
253 static OSSharedPtr<const OSSymbol> gIOPMPSExternalConnectedKey;
254 static OSSharedPtr<const OSSymbol> gIOPMPSExternalChargeCapableKey;
255 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryInstalledKey;
256 static OSSharedPtr<const OSSymbol> gIOPMPSIsChargingKey;
257 static OSSharedPtr<const OSSymbol> gIOPMPSAtWarnLevelKey;
258 static OSSharedPtr<const OSSymbol> gIOPMPSAtCriticalLevelKey;
259 static OSSharedPtr<const OSSymbol> gIOPMPSCurrentCapacityKey;
260 static OSSharedPtr<const OSSymbol> gIOPMPSMaxCapacityKey;
261 static OSSharedPtr<const OSSymbol> gIOPMPSDesignCapacityKey;
262 static OSSharedPtr<const OSSymbol> gIOPMPSTimeRemainingKey;
263 static OSSharedPtr<const OSSymbol> gIOPMPSAmperageKey;
264 static OSSharedPtr<const OSSymbol> gIOPMPSVoltageKey;
265 static OSSharedPtr<const OSSymbol> gIOPMPSCycleCountKey;
266 static OSSharedPtr<const OSSymbol> gIOPMPSMaxErrKey;
267 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterInfoKey;
268 static OSSharedPtr<const OSSymbol> gIOPMPSLocationKey;
269 static OSSharedPtr<const OSSymbol> gIOPMPSErrorConditionKey;
270 static OSSharedPtr<const OSSymbol> gIOPMPSManufacturerKey;
271 static OSSharedPtr<const OSSymbol> gIOPMPSManufactureDateKey;
272 static OSSharedPtr<const OSSymbol> gIOPMPSModelKey;
273 static OSSharedPtr<const OSSymbol> gIOPMPSSerialKey;
274 static OSSharedPtr<const OSSymbol> gIOPMPSLegacyBatteryInfoKey;
275 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryHealthKey;
276 static OSSharedPtr<const OSSymbol> gIOPMPSHealthConfidenceKey;
277 static OSSharedPtr<const OSSymbol> gIOPMPSCapacityEstimatedKey;
278 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryChargeStatusKey;
279 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryTemperatureKey;
280 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsKey;
281 static OSSharedPtr<const OSSymbol> gIOPMPSChargerConfigurationKey;
282 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsIDKey;
283 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsWattsKey;
284 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsRevisionKey;
285 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSerialNumberKey;
286 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsFamilyKey;
287 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsAmperageKey;
288 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsDescriptionKey;
289 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsPMUConfigurationKey;
290 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSourceIDKey;
291 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsErrorFlagsKey;
292 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSharedSourceKey;
293 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsCloakedKey;
294 static OSSharedPtr<const OSSymbol> gIOPMPSInvalidWakeSecondsKey;
295 static OSSharedPtr<const OSSymbol> gIOPMPSPostChargeWaitSecondsKey;
296 static OSSharedPtr<const OSSymbol> gIOPMPSPostDishargeWaitSecondsKey;
297
298 #define kIOSleepSupportedKey "IOSleepSupported"
299 #define kIOPMSystemCapabilitiesKey "System Capabilities"
300 #define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
301
302 #define kIORequestWranglerIdleKey "IORequestIdle"
303 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
304
305 #define kIOSleepWakeFailureString "SleepWakeFailureString"
306 #define kIOEFIBootRomFailureKey "wake-failure"
307 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic"
308
309 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
310 | kIOPMSupportedOnBatt \
311 | kIOPMSupportedOnUPS)
312
313 #define kLocalEvalClamshellCommand (1 << 15)
314 #define kIdleSleepRetryInterval (3 * 60 * 1000)
315
316 // Minimum time in milliseconds after AP wake that we allow idle timer to expire.
317 // We impose this minimum to avoid race conditions in the AP wake path where
318 // userspace clients are not able to acquire power assertions before the idle timer expires.
319 #define kMinimumTimeBeforeIdleSleep 1000
320
321 #define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID)
322
323 enum {
324 kWranglerPowerStateMin = 0,
325 kWranglerPowerStateSleep = 2,
326 kWranglerPowerStateDim = 3,
327 kWranglerPowerStateMax = 4
328 };
329
330 enum {
331 OFF_STATE = 0,
332 RESTART_STATE = 1,
333 SLEEP_STATE = 2,
334 AOT_STATE = 3,
335 ON_STATE = 4,
336 NUM_POWER_STATES
337 };
338
339 const char *
getPowerStateString(uint32_t state)340 getPowerStateString( uint32_t state )
341 {
342 #define POWER_STATE(x) {(uint32_t) x, #x}
343
344 static const IONamedValue powerStates[] = {
345 POWER_STATE( OFF_STATE ),
346 POWER_STATE( RESTART_STATE ),
347 POWER_STATE( SLEEP_STATE ),
348 POWER_STATE( AOT_STATE ),
349 POWER_STATE( ON_STATE ),
350 { 0, NULL }
351 };
352 return IOFindNameForValue(state, powerStates);
353 }
354
355 #define ON_POWER kIOPMPowerOn
356 #define RESTART_POWER kIOPMRestart
357 #define SLEEP_POWER kIOPMAuxPowerOn
358
359 static IOPMPowerState
360 ourPowerStates[NUM_POWER_STATES] =
361 {
362 { .version = 1,
363 .capabilityFlags = 0,
364 .outputPowerCharacter = 0,
365 .inputPowerRequirement = 0 },
366 { .version = 1,
367 .capabilityFlags = kIOPMRestartCapability,
368 .outputPowerCharacter = kIOPMRestart,
369 .inputPowerRequirement = RESTART_POWER },
370 { .version = 1,
371 .capabilityFlags = kIOPMSleepCapability,
372 .outputPowerCharacter = kIOPMSleep,
373 .inputPowerRequirement = SLEEP_POWER },
374 { .version = 1,
375 .capabilityFlags = kIOPMAOTCapability,
376 .outputPowerCharacter = kIOPMAOTPower,
377 .inputPowerRequirement = ON_POWER },
378 { .version = 1,
379 .capabilityFlags = kIOPMPowerOn,
380 .outputPowerCharacter = kIOPMPowerOn,
381 .inputPowerRequirement = ON_POWER },
382 };
383
384 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
385 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
386 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
387 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
388 #define kIOPMRootDomainWakeTypeUser "User"
389 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
390 #define kIOPMRootDomainWakeTypeNetwork "Network"
391 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
392 #define kIOPMRootDomainWakeTypeNotification "Notification"
393 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
394
395 // Special interest that entitles the interested client from receiving
396 // all system messages. Only used by powerd.
397 //
398 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
399
400 // Entitlement required for root domain clients
401 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
402
403 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
404 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
405
406 /*
407 * Aggressiveness
408 */
409 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
410 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
411
412 #define kAggressivesMinValue 1
413
414 const char *
getAggressivenessTypeString(uint32_t type)415 getAggressivenessTypeString( uint32_t type )
416 {
417 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
418
419 static const IONamedValue aggressivenessTypes[] = {
420 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ),
421 AGGRESSIVENESS_TYPE( kPMMinutesToDim ),
422 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ),
423 AGGRESSIVENESS_TYPE( kPMMinutesToSleep ),
424 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ),
425 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ),
426 AGGRESSIVENESS_TYPE( kPMPowerSource),
427 AGGRESSIVENESS_TYPE( kPMMotionSensor ),
428 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ),
429 { 0, NULL }
430 };
431 return IOFindNameForValue(type, aggressivenessTypes);
432 }
433
434 enum {
435 kAggressivesStateBusy = 0x01,
436 kAggressivesStateQuickSpindown = 0x02
437 };
438
439 struct AggressivesRecord {
440 uint32_t flags;
441 uint32_t type;
442 uint32_t value;
443 };
444
445 struct AggressivesRequest {
446 queue_chain_t chain;
447 uint32_t options;
448 uint32_t dataType;
449 union {
450 OSSharedPtr<IOService> service;
451 AggressivesRecord record;
452 } data;
453 };
454
455 enum {
456 kAggressivesRequestTypeService = 1,
457 kAggressivesRequestTypeRecord
458 };
459
460 enum {
461 kAggressivesOptionSynchronous = 0x00000001,
462 kAggressivesOptionQuickSpindownEnable = 0x00000100,
463 kAggressivesOptionQuickSpindownDisable = 0x00000200,
464 kAggressivesOptionQuickSpindownMask = 0x00000300
465 };
466
467 enum {
468 kAggressivesRecordFlagModified = 0x00000001,
469 kAggressivesRecordFlagMinValue = 0x00000002
470 };
471
472 // System Sleep Preventers
473
474 enum {
475 kPMUserDisabledAllSleep = 1,
476 kPMSystemRestartBootingInProgress,
477 kPMConfigPreventSystemSleep,
478 kPMChildPreventSystemSleep,
479 kPMCPUAssertion,
480 kPMPCIUnsupported,
481 kPMDKNotReady,
482 };
483
484 const char *
getSystemSleepPreventerString(uint32_t preventer)485 getSystemSleepPreventerString( uint32_t preventer )
486 {
487 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
488 static const IONamedValue systemSleepPreventers[] = {
489 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ),
490 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ),
491 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ),
492 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ),
493 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ),
494 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ),
495 SYSTEM_SLEEP_PREVENTER( kPMDKNotReady ),
496 { 0, NULL }
497 };
498 return IOFindNameForValue(preventer, systemSleepPreventers);
499 }
500
501 // gDarkWakeFlags
502 enum {
503 kDarkWakeFlagPromotionNone = 0x0000,
504 kDarkWakeFlagPromotionEarly = 0x0001, // promote before gfx clamp
505 kDarkWakeFlagPromotionLate = 0x0002, // promote after gfx clamp
506 kDarkWakeFlagPromotionMask = 0x0003,
507 kDarkWakeFlagAlarmIsDark = 0x0100,
508 kDarkWakeFlagAudioNotSuppressed = 0x0200,
509 kDarkWakeFlagUserWakeWorkaround = 0x1000
510 };
511
512 // gClamshellFlags
513 // The workaround for 9157444 is enabled at compile time using the
514 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below.
515 enum {
516 kClamshell_WAR_38378787 = 0x00000001,
517 kClamshell_WAR_47715679 = 0x00000002,
518 kClamshell_WAR_58009435 = 0x00000004
519 };
520
521 // acceptSystemWakeEvents()
522 enum {
523 kAcceptSystemWakeEvents_Disable = 0,
524 kAcceptSystemWakeEvents_Enable,
525 kAcceptSystemWakeEvents_Reenable
526 };
527
528 static IOPMrootDomain * gRootDomain;
529 static IORootParent * gPatriarch;
530 static IONotifier * gSysPowerDownNotifier = NULL;
531 static UInt32 gSleepOrShutdownPending = 0;
532 static UInt32 gWillShutdown = 0;
533 static UInt32 gPagingOff = 0;
534 static UInt32 gSleepWakeUUIDIsSet = false;
535 static uint32_t gAggressivesState = 0;
536 uint32_t gHaltTimeMaxLog;
537 uint32_t gHaltTimeMaxPanic;
538 IOLock * gHaltLogLock;
539 static char * gHaltLog;
540 enum { kHaltLogSize = 2048 };
541 static size_t gHaltLogPos;
542 static uint64_t gHaltStartTime;
543 static char gKextNameBuf[64];
544 static size_t gKextNamePos;
545 static bool gKextNameEnd;
546
547 uuid_string_t bootsessionuuid_string;
548
549 #if defined(XNU_TARGET_OS_OSX)
550 #if DISPLAY_WRANGLER_PRESENT
551 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionNone;
552 #elif defined(__arm64__)
553 // Enable temporary full wake promotion workarounds
554 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
555 #else
556 // Enable full wake promotion workarounds
557 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
558 #endif
559 #else /* !defined(XNU_TARGET_OS_OSX) */
560 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionEarly;
561 #endif /* !defined(XNU_TARGET_OS_OSX) */
562
563 static uint32_t gNoIdleFlag = 0;
564 static uint32_t gSleepDisabledFlag = 0;
565 static uint32_t gSwdPanic = 1;
566 static uint32_t gSwdSleepTimeout = 0;
567 static uint32_t gSwdWakeTimeout = 0;
568 static uint32_t gSwdSleepWakeTimeout = 0;
569 static PMStatsStruct gPMStats;
570 #if DEVELOPMENT || DEBUG
571 static uint32_t swd_panic_phase;
572 #endif
573
574 static uint32_t gClamshellFlags = 0
575 #if defined(__i386__) || defined(__x86_64__)
576 | kClamshell_WAR_58009435
577 #endif
578 ;
579
580 #if HIBERNATION
581
582 #if defined(__arm64__)
583 static IOReturn
defaultSleepPolicyHandler(void * ctx,const IOPMSystemSleepPolicyVariables * vars,IOPMSystemSleepParameters * params)584 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params)
585 {
586 uint32_t sleepType = kIOPMSleepTypeDeepIdle;
587
588 assert(vars->signature == kIOPMSystemSleepPolicySignature);
589 assert(vars->version == kIOPMSystemSleepPolicyVersion);
590
591 // Hibernation enabled and either user forced hibernate or low battery sleep
592 if ((vars->hibernateMode & kIOHibernateModeOn) &&
593 (((vars->hibernateMode & kIOHibernateModeSleep) == 0) ||
594 (vars->sleepFactors & kIOPMSleepFactorBatteryLow))) {
595 sleepType = kIOPMSleepTypeHibernate;
596 }
597 params->version = kIOPMSystemSleepParametersVersion;
598 params->sleepType = sleepType;
599 return kIOReturnSuccess;
600 }
601 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = &defaultSleepPolicyHandler;
602 #else /* defined(__arm64__) */
603 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = NULL;
604 #endif /* defined(__arm64__) */
605
606 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
607 static void * gSleepPolicyTarget;
608 #endif
609
610 struct timeval gIOLastSleepTime;
611 struct timeval gIOLastWakeTime;
612 AbsoluteTime gIOLastWakeAbsTime;
613 AbsoluteTime gIOLastSleepAbsTime;
614
615 struct timeval gIOLastUserSleepTime;
616
617 static char gWakeReasonString[128];
618 static char gBootReasonString[80];
619 static char gShutdownReasonString[80];
620 static bool gWakeReasonSysctlRegistered = false;
621 static bool gBootReasonSysctlRegistered = false;
622 static bool gShutdownReasonSysctlRegistered = false;
623 static bool gWillShutdownSysctlRegistered = false;
624 static AbsoluteTime gUserActiveAbsTime;
625 static AbsoluteTime gUserInactiveAbsTime;
626
627 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
628 static bool gSpinDumpBufferFull = false;
629 #endif
630
631 z_stream swd_zs;
632 vm_offset_t swd_zs_zmem;
633 //size_t swd_zs_zsize;
634 size_t swd_zs_zoffset;
635 #if defined(__i386__) || defined(__x86_64__)
636 IOCPU *currentShutdownTarget = NULL;
637 #endif
638
639 static unsigned int gPMHaltBusyCount;
640 static unsigned int gPMHaltIdleCount;
641 static int gPMHaltDepth;
642 static uint32_t gPMHaltMessageType;
643 static IOLock * gPMHaltLock = NULL;
644 static OSSharedPtr<OSArray> gPMHaltArray;
645 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey;
646 static bool gPMQuiesced;
647
648 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
649 #define kCPUUnknownIndex 9999999
650 enum {
651 kInformAC = 0,
652 kInformLid = 1,
653 kInformableCount = 2
654 };
655
656 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut;
657 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel;
658 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow;
659 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt;
660 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow;
661
662 #define kBadPMFeatureID 0
663
664 /*
665 * PMSettingHandle
666 * Opaque handle passed to clients of registerPMSettingController()
667 */
668 class PMSettingHandle : public OSObject
669 {
670 OSDeclareFinalStructors( PMSettingHandle );
671 friend class PMSettingObject;
672
673 private:
674 PMSettingObject *pmso;
675 void free(void) APPLE_KEXT_OVERRIDE;
676 };
677
678 /*
679 * PMSettingObject
680 * Internal object to track each PM setting controller
681 */
682 class PMSettingObject : public OSObject
683 {
684 OSDeclareFinalStructors( PMSettingObject );
685 friend class IOPMrootDomain;
686
687 private:
688 queue_head_t calloutQueue;
689 thread_t waitThread;
690 IOPMrootDomain *parent;
691 PMSettingHandle *pmsh;
692 IOPMSettingControllerCallback func;
693 OSObject *target;
694 uintptr_t refcon;
695 OSDataAllocation<uint32_t> publishedFeatureID;
696 uint32_t settingCount;
697 bool disabled;
698
699 void free(void) APPLE_KEXT_OVERRIDE;
700
701 public:
702 static PMSettingObject *pmSettingObject(
703 IOPMrootDomain *parent_arg,
704 IOPMSettingControllerCallback handler_arg,
705 OSObject *target_arg,
706 uintptr_t refcon_arg,
707 uint32_t supportedPowerSources,
708 const OSSymbol *settings[],
709 OSObject **handle_obj);
710
711 IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
712 void clientHandleFreed(void);
713 };
714
715 struct PMSettingCallEntry {
716 queue_chain_t link;
717 thread_t thread;
718 };
719
720 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
721 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
722 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
723 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
724
725 /*
726 * PMTraceWorker
727 * Internal helper object for logging trace points to RTC
728 * IOPMrootDomain and only IOPMrootDomain should instantiate
729 * exactly one of these.
730 */
731
732 typedef void (*IOPMTracePointHandler)(
733 void * target, uint32_t code, uint32_t data );
734
735 class PMTraceWorker : public OSObject
736 {
737 OSDeclareDefaultStructors(PMTraceWorker);
738 public:
739 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
740
741 static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * );
742 void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
743 void tracePoint(uint8_t phase);
744 void traceDetail(uint32_t detail);
745 void traceComponentWakeProgress(uint32_t component, uint32_t data);
746 int recordTopLevelPCIDevice(IOService *);
747 void RTC_TRACE(void);
748 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
749
750 IOPMTracePointHandler tracePointHandler;
751 void * tracePointTarget;
752 uint64_t getPMStatusCode();
753 uint8_t getTracePhase();
754 uint32_t getTraceData();
755 private:
756 IOPMrootDomain *owner;
757 IOLock *pmTraceWorkerLock;
758 OSSharedPtr<OSArray> pciDeviceBitMappings;
759
760 uint8_t addedToRegistry;
761 uint8_t tracePhase;
762 uint32_t traceData32;
763 uint8_t loginWindowData;
764 uint8_t coreDisplayData;
765 uint8_t coreGraphicsData;
766 };
767
768 /*
769 * this should be treated as POD, as it's byte-copied around
770 * and we cannot rely on d'tor firing at the right time
771 */
772 struct PMAssertStruct {
773 IOPMDriverAssertionID id;
774 IOPMDriverAssertionType assertionBits;
775 uint64_t createdTime;
776 uint64_t modifiedTime;
777 const OSSymbol *ownerString;
778 IOService *ownerService;
779 uint64_t registryEntryID;
780 IOPMDriverAssertionLevel level;
781 uint64_t assertCPUStartTime;
782 uint64_t assertCPUDuration;
783 };
784 OSDefineValueObjectForDependentType(PMAssertStruct)
785
786 /*
787 * PMAssertionsTracker
788 * Tracks kernel and user space PM assertions
789 */
790 class PMAssertionsTracker : public OSObject
791 {
792 OSDeclareFinalStructors(PMAssertionsTracker);
793 public:
794 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * );
795
796 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
797 IOReturn releaseAssertion(IOPMDriverAssertionID);
798 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
799 IOReturn setUserAssertionLevels(IOPMDriverAssertionType);
800
801 OSSharedPtr<OSArray> copyAssertionsArray(void);
802 IOPMDriverAssertionType getActivatedAssertions(void);
803 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType);
804
805 IOReturn handleCreateAssertion(OSValueObject<PMAssertStruct> *);
806 IOReturn handleReleaseAssertion(IOPMDriverAssertionID);
807 IOReturn handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
808 IOReturn handleSetUserAssertionLevels(void * arg0);
809 void publishProperties(void);
810 void reportCPUBitAccounting(void);
811 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *);
812
813 private:
814 uint32_t tabulateProducerCount;
815 uint32_t tabulateConsumerCount;
816
817 uint64_t maxAssertCPUDuration;
818 uint64_t maxAssertCPUEntryId;
819
820 void tabulate(void);
821 void updateCPUBitAccounting(PMAssertStruct * assertStruct);
822
823 IOPMrootDomain *owner;
824 OSSharedPtr<OSArray> assertionsArray;
825 IOLock *assertionsArrayLock;
826 IOPMDriverAssertionID issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
827 IOPMDriverAssertionType assertionsKernel;
828 IOPMDriverAssertionType assertionsUser;
829 IOPMDriverAssertionType assertionsCombined;
830 };
831
832 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
833
834 /*
835 * PMHaltWorker
836 * Internal helper object for Shutdown/Restart notifications.
837 */
838 #define kPMHaltMaxWorkers 8
839 #define kPMHaltTimeoutMS 100
840
841 class PMHaltWorker : public OSObject
842 {
843 OSDeclareFinalStructors( PMHaltWorker );
844
845 public:
846 IOService * service;// service being worked on
847 AbsoluteTime startTime; // time when work started
848 int depth; // work on nubs at this PM-tree depth
849 int visits; // number of nodes visited (debug)
850 IOLock * lock;
851 bool timeout;// service took too long
852
853 static PMHaltWorker * worker( void );
854 static void main( void * arg, wait_result_t waitResult );
855 static void work( PMHaltWorker * me );
856 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
857 virtual void free( void ) APPLE_KEXT_OVERRIDE;
858 };
859
OSDefineMetaClassAndFinalStructors(PMHaltWorker,OSObject)860 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
861
862
863 #define super IOService
864 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
865
866 boolean_t
867 IOPMRootDomainGetWillShutdown(void)
868 {
869 return gWillShutdown != 0;
870 }
871
872 static void
IOPMRootDomainWillShutdown(void)873 IOPMRootDomainWillShutdown(void)
874 {
875 if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
876 IOService::willShutdown();
877 for (int i = 0; i < 100; i++) {
878 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
879 break;
880 }
881 IOSleep( 100 );
882 }
883 }
884 }
885
886 extern "C" IONotifier *
registerSleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)887 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
888 {
889 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
890 }
891
892 extern "C" IONotifier *
registerPrioritySleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)893 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
894 {
895 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
896 }
897
898 extern "C" IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon)899 acknowledgeSleepWakeNotification(void * PMrefcon)
900 {
901 return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
902 }
903
904 extern "C" IOReturn
vetoSleepWakeNotification(void * PMrefcon)905 vetoSleepWakeNotification(void * PMrefcon)
906 {
907 return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
908 }
909
910 extern "C" IOReturn
rootDomainRestart(void)911 rootDomainRestart( void )
912 {
913 return gRootDomain->restartSystem();
914 }
915
916 extern "C" IOReturn
rootDomainShutdown(void)917 rootDomainShutdown( void )
918 {
919 return gRootDomain->shutdownSystem();
920 }
921
922 static void
halt_log_putc(char c)923 halt_log_putc(char c)
924 {
925 if (gHaltLogPos >= (kHaltLogSize - 2)) {
926 return;
927 }
928 gHaltLog[gHaltLogPos++] = c;
929 }
930
931 extern "C" void
932 _doprnt_log(const char *fmt,
933 va_list *argp,
934 void (*putc)(char),
935 int radix);
936
937 static int
halt_log(const char * fmt,...)938 halt_log(const char *fmt, ...)
939 {
940 va_list listp;
941
942 va_start(listp, fmt);
943 _doprnt_log(fmt, &listp, &halt_log_putc, 16);
944 va_end(listp);
945
946 return 0;
947 }
948
949 extern "C" void
halt_log_enter(const char * what,const void * pc,uint64_t time)950 halt_log_enter(const char * what, const void * pc, uint64_t time)
951 {
952 uint64_t nano, millis;
953
954 if (!gHaltLog) {
955 return;
956 }
957 absolutetime_to_nanoseconds(time, &nano);
958 millis = nano / NSEC_PER_MSEC;
959 if (millis < 100) {
960 return;
961 }
962
963 IOLockLock(gHaltLogLock);
964 if (pc) {
965 halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
966 OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
967 OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
968 } else {
969 halt_log("%s: %qd ms\n", what, millis);
970 }
971
972 gHaltLog[gHaltLogPos] = 0;
973 IOLockUnlock(gHaltLogLock);
974 }
975
976 extern uint32_t gFSState;
977
978 extern "C" void
IOSystemShutdownNotification(int howto,int stage)979 IOSystemShutdownNotification(int howto, int stage)
980 {
981 uint64_t startTime;
982
983 if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
984 #if defined(XNU_TARGET_OS_OSX)
985 uint64_t nano, millis;
986 startTime = mach_absolute_time();
987 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
988 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
989 millis = nano / NSEC_PER_MSEC;
990 if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
991 printf("waitQuiet() for unmount %qd ms\n", millis);
992 }
993 #endif /* defined(XNU_TARGET_OS_OSX) */
994 return;
995 }
996
997 if (kIOSystemShutdownNotificationTerminateDEXTs == stage) {
998 uint64_t nano, millis;
999 startTime = mach_absolute_time();
1000 IOServicePH::systemHalt(howto);
1001 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
1002 millis = nano / NSEC_PER_MSEC;
1003 if (true || (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog))) {
1004 printf("IOServicePH::systemHalt took %qd ms\n", millis);
1005 }
1006 return;
1007 }
1008
1009 assert(kIOSystemShutdownNotificationStageProcessExit == stage);
1010
1011 IOLockLock(gHaltLogLock);
1012 if (!gHaltLog) {
1013 gHaltLog = IONewData(char, (vm_size_t)kHaltLogSize);
1014 gHaltStartTime = mach_absolute_time();
1015 if (gHaltLog) {
1016 halt_log_putc('\n');
1017 }
1018 }
1019 IOLockUnlock(gHaltLogLock);
1020
1021 startTime = mach_absolute_time();
1022 IOPMRootDomainWillShutdown();
1023 halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
1024 #if HIBERNATION
1025 startTime = mach_absolute_time();
1026 IOHibernateSystemPostWake(true);
1027 halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
1028 #endif
1029 if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1030 gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1031 }
1032 }
1033
1034 extern "C" int sync_internal(void);
1035
1036 /*
1037 * A device is always in the highest power state which satisfies its driver,
1038 * its policy-maker, and any power children it has, but within the constraint
1039 * of the power state provided by its parent. The driver expresses its desire by
1040 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
1041 * changePowerStateToPriv(), and the children express their desires by calling
1042 * requestPowerDomainState().
1043 *
1044 * The Root Power Domain owns the policy for idle and demand sleep for the system.
1045 * It is a power-managed IOService just like the others in the system.
1046 * It implements several power states which map to what we see as Sleep and On.
1047 *
1048 * The sleep policy is as follows:
1049 * 1. Sleep is prevented if the case is open so that nobody will think the machine
1050 * is off and plug/unplug cards.
1051 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1052 * 3. System cannot Sleep if some object in the tree is in a power state marked
1053 * kIOPMPreventSystemSleep.
1054 *
1055 * These three conditions are enforced using the "driver clamp" by calling
1056 * changePowerStateTo(). For example, if the case is opened,
1057 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
1058 * of the desires of the children of the root or the state of the other clamp.
1059 *
1060 * Demand Sleep is initiated by pressing the front panel power button, closing
1061 * the clamshell, or selecting the menu item. In this case the root's parent
1062 * actually initiates the power state change so that the root domain has no
1063 * choice and does not give applications the opportunity to veto the change.
1064 *
1065 * Idle Sleep occurs if no objects in the tree are in a state marked
1066 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
1067 * the root on, so it sets the "policy-maker clamp" by calling
1068 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1069 * This timer is set for the difference between the sleep timeout slider and the
1070 * display dim timeout slider. When the timer expires, it releases its clamp and
1071 * now nothing is holding it awake, so it falls asleep.
1072 *
1073 * Demand sleep is prevented when the system is booting. When preferences are
1074 * transmitted by the loginwindow at the end of boot, a flag is cleared,
1075 * and this allows subsequent Demand Sleep.
1076 */
1077
1078 //******************************************************************************
1079
1080 IOPMrootDomain *
construct(void)1081 IOPMrootDomain::construct( void )
1082 {
1083 IOPMrootDomain *root;
1084
1085 root = new IOPMrootDomain;
1086 if (root) {
1087 root->init();
1088 }
1089
1090 return root;
1091 }
1092
1093 //******************************************************************************
1094 // updateConsoleUsersCallout
1095 //
1096 //******************************************************************************
1097
1098 static void
updateConsoleUsersCallout(thread_call_param_t p0,thread_call_param_t p1)1099 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1100 {
1101 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1102 rootDomain->updateConsoleUsers();
1103 }
1104
1105 void
updateConsoleUsers(void)1106 IOPMrootDomain::updateConsoleUsers(void)
1107 {
1108 IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1109 updateTasksSuspend(kTasksSuspendUnsuspended, kTasksSuspendNoChange);
1110 }
1111
1112 bool
updateTasksSuspend(int newTasksSuspended,int newAOTTasksSuspended)1113 IOPMrootDomain::updateTasksSuspend(int newTasksSuspended, int newAOTTasksSuspended)
1114 {
1115 bool newSuspend;
1116
1117 WAKEEVENT_LOCK();
1118 if (newTasksSuspended != kTasksSuspendNoChange) {
1119 tasksSuspended = (newTasksSuspended != kTasksSuspendUnsuspended);
1120 }
1121 if (newAOTTasksSuspended != kTasksSuspendNoChange) {
1122 _aotTasksSuspended = (newAOTTasksSuspended != kTasksSuspendUnsuspended);
1123 }
1124 newSuspend = (tasksSuspended || _aotTasksSuspended);
1125 if (newSuspend == tasksSuspendState) {
1126 WAKEEVENT_UNLOCK();
1127 return false;
1128 }
1129 tasksSuspendState = newSuspend;
1130 WAKEEVENT_UNLOCK();
1131 tasks_system_suspend(newSuspend);
1132 return true;
1133 }
1134
1135 //******************************************************************************
1136
1137 static void
disk_sync_callout(thread_call_param_t p0,thread_call_param_t p1)1138 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1139 {
1140 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1141 uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
1142 uint32_t powerState = rootDomain->getPowerState();
1143
1144 DLOG("disk_sync_callout ps=%u\n", powerState);
1145
1146 if (ON_STATE == powerState) {
1147 sync_internal();
1148
1149 #if HIBERNATION
1150 // Block sleep until trim issued on previous wake path is completed.
1151 IOHibernateSystemPostWake(true);
1152 #endif
1153 }
1154 #if HIBERNATION
1155 else {
1156 IOHibernateSystemPostWake(false);
1157
1158 rootDomain->sleepWakeDebugSaveSpinDumpFile();
1159 }
1160 #endif
1161
1162 rootDomain->allowPowerChange(notifyRef);
1163 DLOG("disk_sync_callout finish\n");
1164 }
1165
1166 //******************************************************************************
1167 static UInt32
computeDeltaTimeMS(const AbsoluteTime * startTime,AbsoluteTime * elapsedTime)1168 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1169 {
1170 AbsoluteTime endTime;
1171 UInt64 nano = 0;
1172
1173 clock_get_uptime(&endTime);
1174 if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1175 *elapsedTime = 0;
1176 } else {
1177 SUB_ABSOLUTETIME(&endTime, startTime);
1178 absolutetime_to_nanoseconds(endTime, &nano);
1179 *elapsedTime = endTime;
1180 }
1181
1182 return (UInt32)(nano / NSEC_PER_MSEC);
1183 }
1184
1185 //******************************************************************************
1186
1187 static int
1188 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1189 {
1190 struct timeval *swt = (struct timeval *)arg1;
1191 struct proc *p = req->p;
1192
1193 if (p == kernproc) {
1194 return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
1195 } else if (proc_is64bit(p)) {
1196 struct user64_timeval t = {};
1197 t.tv_sec = swt->tv_sec;
1198 t.tv_usec = swt->tv_usec;
1199 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1200 } else {
1201 struct user32_timeval t = {};
1202 t.tv_sec = (typeof(t.tv_sec))swt->tv_sec;
1203 t.tv_usec = swt->tv_usec;
1204 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1205 }
1206 }
1207
1208 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1209 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1210 &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1211
1212 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1213 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1214 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1215
1216 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
1217 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
1218 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
1219 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
1220
1221 static int
1222 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1223 {
1224 int new_value, changed, error;
1225
1226 if (!gWillShutdownSysctlRegistered) {
1227 return ENOENT;
1228 }
1229
1230 error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1231 if (changed) {
1232 if (!gWillShutdown && (new_value == 1)) {
1233 IOPMRootDomainWillShutdown();
1234 } else {
1235 error = EINVAL;
1236 }
1237 }
1238 return error;
1239 }
1240
1241 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1242 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1243 NULL, 0, sysctl_willshutdown, "I", "");
1244
1245 #if defined(XNU_TARGET_OS_OSX)
1246
1247 static int
sysctl_progressmeterenable(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1248 sysctl_progressmeterenable
1249 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1250 {
1251 int error;
1252 int new_value, changed;
1253
1254 error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1255
1256 if (changed) {
1257 vc_enable_progressmeter(new_value);
1258 }
1259
1260 return error;
1261 }
1262
1263 static int
sysctl_progressmeter(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1264 sysctl_progressmeter
1265 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1266 {
1267 int error;
1268 int new_value, changed;
1269
1270 error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1271
1272 if (changed) {
1273 vc_set_progressmeter(new_value);
1274 }
1275
1276 return error;
1277 }
1278
1279 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1280 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1281 NULL, 0, sysctl_progressmeterenable, "I", "");
1282
1283 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1284 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1285 NULL, 0, sysctl_progressmeter, "I", "");
1286
1287 #endif /* defined(XNU_TARGET_OS_OSX) */
1288
1289
1290
1291 static int
sysctl_consoleoptions(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1292 sysctl_consoleoptions
1293 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1294 {
1295 int error, changed;
1296 uint32_t new_value;
1297
1298 error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1299
1300 if (changed) {
1301 vc_user_options.options = new_value;
1302 }
1303
1304 return error;
1305 }
1306
1307 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1308 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1309 NULL, 0, sysctl_consoleoptions, "I", "");
1310
1311
1312 static int
1313 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1314 {
1315 return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1316 }
1317
1318 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1319 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1320 NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1321
1322
1323 static int
1324 sysctl_wakereason SYSCTL_HANDLER_ARGS
1325 {
1326 char wr[sizeof(gWakeReasonString)];
1327
1328 wr[0] = '\0';
1329 if (gRootDomain && gWakeReasonSysctlRegistered) {
1330 gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1331 } else {
1332 return ENOENT;
1333 }
1334
1335 return sysctl_io_string(req, wr, 0, 0, NULL);
1336 }
1337
1338 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1339 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1340 NULL, 0, sysctl_wakereason, "A", "wakereason");
1341
1342 static int
1343 sysctl_bootreason SYSCTL_HANDLER_ARGS
1344 {
1345 if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) {
1346 return ENOENT;
1347 }
1348
1349 return sysctl_io_string(req, gBootReasonString, 0, 0, NULL);
1350 }
1351
1352 SYSCTL_PROC(_kern, OID_AUTO, bootreason,
1353 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1354 NULL, 0, sysctl_bootreason, "A", "");
1355
1356 static int
1357 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1358 {
1359 char sr[sizeof(gShutdownReasonString)];
1360
1361 sr[0] = '\0';
1362 if (gRootDomain && gShutdownReasonSysctlRegistered) {
1363 gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1364 } else {
1365 return ENOENT;
1366 }
1367
1368 return sysctl_io_string(req, sr, 0, 0, NULL);
1369 }
1370
1371 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1372 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1373 NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1374
1375 static int
1376 sysctl_targettype SYSCTL_HANDLER_ARGS
1377 {
1378 IOService * root;
1379 OSSharedPtr<OSObject> obj;
1380 OSData * data;
1381 char tt[32];
1382
1383 tt[0] = '\0';
1384 root = IOService::getServiceRoot();
1385 if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1386 if ((data = OSDynamicCast(OSData, obj.get()))) {
1387 strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1388 }
1389 }
1390 return sysctl_io_string(req, tt, 0, 0, NULL);
1391 }
1392
1393 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1394 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1395 NULL, 0, sysctl_targettype, "A", "targettype");
1396
1397 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1398 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1399 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1400 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1401 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1402 #if DEVELOPMENT || DEBUG
1403 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
1404 #if defined(XNU_TARGET_OS_OSX)
1405 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, "");
1406 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1407 #endif /* defined(XNU_TARGET_OS_OSX) */
1408 #endif /* DEVELOPMENT || DEBUG */
1409
1410 //******************************************************************************
1411 // AOT
1412
1413 static int
1414 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1415 {
1416 if (NULL == gRootDomain) {
1417 return ENOENT;
1418 }
1419 if (NULL == gRootDomain->_aotMetrics) {
1420 IOPMAOTMetrics nullMetrics = {};
1421 return sysctl_io_opaque(req, &nullMetrics, sizeof(IOPMAOTMetrics), NULL);
1422 }
1423 return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1424 }
1425
1426 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
1427 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1428 NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
1429
1430
1431 static int
update_aotmode(uint32_t mode)1432 update_aotmode(uint32_t mode)
1433 {
1434 int result;
1435
1436 if (!gIOPMWorkLoop) {
1437 return ENOENT;
1438 }
1439 result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1440 unsigned int oldCount;
1441
1442 if (mode && !gRootDomain->_aotMetrics) {
1443 gRootDomain->_aotMetrics = IOMallocType(IOPMAOTMetrics);
1444 }
1445
1446 oldCount = gRootDomain->idleSleepPreventersCount();
1447 gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1448 gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1449 return 0;
1450 });
1451 return result;
1452 }
1453
1454 static int
sysctl_aotmodebits(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1455 sysctl_aotmodebits
1456 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1457 {
1458 int error, changed;
1459 uint32_t new_value;
1460
1461 if (NULL == gRootDomain) {
1462 return ENOENT;
1463 }
1464 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1465 if (changed && gIOPMWorkLoop) {
1466 error = update_aotmode(new_value);
1467 }
1468
1469 return error;
1470 }
1471
1472 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1473 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1474 NULL, 0, sysctl_aotmodebits, "I", "");
1475
1476 static int
sysctl_aotmode(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1477 sysctl_aotmode
1478 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1479 {
1480 int error, changed;
1481 uint32_t new_value;
1482
1483 if (NULL == gRootDomain) {
1484 return ENOENT;
1485 }
1486 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1487 if (changed && gIOPMWorkLoop) {
1488 if (new_value) {
1489 new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1490 }
1491 error = update_aotmode(new_value);
1492 }
1493
1494 return error;
1495 }
1496
1497 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
1498 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1499 NULL, 0, sysctl_aotmode, "I", "");
1500
1501 //******************************************************************************
1502
1503 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey;
1504 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey;
1505 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey;
1506 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey;
1507 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey;
1508 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey;
1509 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey;
1510 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey;
1511 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey;
1512 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey;
1513 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey;
1514 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey;
1515
1516 //******************************************************************************
1517 // start
1518 //
1519 //******************************************************************************
1520
1521 #define kRootDomainSettingsCount 20
1522 #define kRootDomainNoPublishSettingsCount 4
1523
1524 bool
start(IOService * nub)1525 IOPMrootDomain::start( IOService * nub )
1526 {
1527 OSSharedPtr<OSIterator> psIterator;
1528 OSSharedPtr<OSDictionary> tmpDict;
1529
1530 super::start(nub);
1531
1532 gRootDomain = this;
1533 gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1534 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1535 gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
1536 gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
1537 gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1538 gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
1539 gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1540 gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1541 gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1542 gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1543 gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1544 gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey);
1545
1546 gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1547 gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1548 gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1549 gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1550 gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1551
1552 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1553 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1554 gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1555
1556 OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1557 {
1558 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1559 gIOPMSettingAutoWakeSecondsKey,
1560 gIOPMSettingAutoPowerSecondsKey,
1561 gIOPMSettingAutoWakeCalendarKey,
1562 gIOPMSettingAutoPowerCalendarKey,
1563 gIOPMSettingDebugWakeRelativeKey,
1564 gIOPMSettingDebugPowerRelativeKey,
1565 OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1566 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1567 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1568 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1569 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1570 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1571 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1572 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1573 OSSymbol::withCString(kIOPMStateConsoleShutdown),
1574 OSSymbol::withCString(kIOPMSettingProModeControl),
1575 OSSymbol::withCString(kIOPMSettingProModeDefer),
1576 gIOPMSettingSilentRunningKey,
1577 gIOPMSettingLowLatencyAudioModeKey,
1578 };
1579
1580 OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1581 {
1582 OSSymbol::withCString(kIOPMSettingProModeControl),
1583 OSSymbol::withCString(kIOPMSettingProModeDefer),
1584 gIOPMSettingSilentRunningKey,
1585 gIOPMSettingLowLatencyAudioModeKey,
1586 };
1587
1588 #if DEVELOPMENT || DEBUG
1589 #if defined(XNU_TARGET_OS_OSX)
1590 PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1591 PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags));
1592 #endif /* defined(XNU_TARGET_OS_OSX) */
1593 #endif /* DEVELOPMENT || DEBUG */
1594
1595 PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1596 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1597 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1598 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1599 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1600 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1601
1602 // read noidle setting from Device Tree
1603 if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
1604 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
1605 }
1606
1607 queue_init(&aggressivesQueue);
1608 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1609 aggressivesData = OSData::withCapacity(
1610 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1611
1612 featuresDictLock = IOLockAlloc();
1613 settingsCtrlLock = IOLockAlloc();
1614 wakeEventLock = IOLockAlloc();
1615 gHaltLogLock = IOLockAlloc();
1616 setPMRootDomain(this);
1617
1618 extraSleepTimer = thread_call_allocate(
1619 idleSleepTimerExpired,
1620 (thread_call_param_t) this);
1621
1622 powerButtonDown = thread_call_allocate(
1623 powerButtonDownCallout,
1624 (thread_call_param_t) this);
1625
1626 powerButtonUp = thread_call_allocate(
1627 powerButtonUpCallout,
1628 (thread_call_param_t) this);
1629
1630 diskSyncCalloutEntry = thread_call_allocate(
1631 &disk_sync_callout,
1632 (thread_call_param_t) this);
1633 updateConsoleUsersEntry = thread_call_allocate(
1634 &updateConsoleUsersCallout,
1635 (thread_call_param_t) this);
1636
1637 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1638 fullWakeThreadCall = thread_call_allocate_with_options(
1639 OSMemberFunctionCast(thread_call_func_t, this,
1640 &IOPMrootDomain::fullWakeDelayedWork),
1641 (thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL,
1642 THREAD_CALL_OPTIONS_ONCE);
1643 #endif
1644
1645 setProperty(kIOSleepSupportedKey, true);
1646
1647 bzero(&gPMStats, sizeof(gPMStats));
1648
1649 pmTracer = PMTraceWorker::tracer(this);
1650
1651 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1652
1653 userDisabledAllSleep = false;
1654 systemBooting = true;
1655 idleSleepEnabled = false;
1656 sleepSlider = 0;
1657 idleSleepTimerPending = false;
1658 wrangler = NULL;
1659 clamshellClosed = false;
1660 clamshellExists = false;
1661 #if DISPLAY_WRANGLER_PRESENT
1662 clamshellDisabled = true;
1663 #else
1664 clamshellDisabled = false;
1665 #endif
1666 clamshellIgnoreClose = false;
1667 acAdaptorConnected = true;
1668 clamshellSleepDisableMask = 0;
1669 gWakeReasonString[0] = '\0';
1670
1671 // Initialize to user active.
1672 // Will never transition to user inactive w/o wrangler.
1673 fullWakeReason = kFullWakeReasonLocalUser;
1674 userIsActive = userWasActive = true;
1675 clock_get_uptime(&gUserActiveAbsTime);
1676 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
1677
1678 // Set the default system capabilities at boot.
1679 _currentCapability = kIOPMSystemCapabilityCPU |
1680 kIOPMSystemCapabilityGraphics |
1681 kIOPMSystemCapabilityAudio |
1682 kIOPMSystemCapabilityNetwork;
1683
1684 _pendingCapability = _currentCapability;
1685 _desiredCapability = _currentCapability;
1686 _highestCapability = _currentCapability;
1687 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1688
1689 queuedSleepWakeUUIDString = NULL;
1690 initializeBootSessionUUID();
1691 pmStatsAppResponses = OSArray::withCapacity(5);
1692 _statsNameKey = OSSymbol::withCString(kIOPMStatsNameKey);
1693 _statsPIDKey = OSSymbol::withCString(kIOPMStatsPIDKey);
1694 _statsTimeMSKey = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1695 _statsResponseTypeKey = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1696 _statsMessageTypeKey = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1697 _statsPowerCapsKey = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1698 assertOnWakeSecs = -1;// Invalid value to prevent updates
1699
1700 pmStatsLock = IOLockAlloc();
1701 idxPMCPUClamshell = kCPUUnknownIndex;
1702 idxPMCPULimitedPower = kCPUUnknownIndex;
1703
1704 tmpDict = OSDictionary::withCapacity(1);
1705 setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1706
1707 // Set a default "SystemPowerProfileOverrideDict" for platform
1708 // drivers without any overrides.
1709 if (!propertyExists(kIOPMSystemDefaultOverrideKey)) {
1710 tmpDict = OSDictionary::withCapacity(1);
1711 setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get());
1712 }
1713
1714 settingsCallbacks = OSDictionary::withCapacity(1);
1715
1716 // Create a list of the valid PM settings that we'll relay to
1717 // interested clients in setProperties() => setPMSetting()
1718 allowedPMSettings = OSArray::withObjects(
1719 (const OSObject **)settingsArr,
1720 kRootDomainSettingsCount,
1721 0);
1722
1723 // List of PM settings that should not automatically publish itself
1724 // as a feature when registered by a listener.
1725 noPublishPMSettings = OSArray::withObjects(
1726 (const OSObject **)noPublishSettingsArr,
1727 kRootDomainNoPublishSettingsCount,
1728 0);
1729
1730 fPMSettingsDict = OSDictionary::withCapacity(5);
1731 preventIdleSleepList = OSSet::withCapacity(8);
1732 preventSystemSleepList = OSSet::withCapacity(2);
1733
1734 PMinit(); // creates gIOPMWorkLoop
1735 gIOPMWorkLoop = getIOPMWorkloop();
1736
1737 // Create IOPMPowerStateQueue used to queue external power
1738 // events, and to handle those events on the PM work loop.
1739 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1740 this, OSMemberFunctionCast(IOEventSource::Action, this,
1741 &IOPMrootDomain::dispatchPowerEvent));
1742 gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1743
1744 _aotMode = 0;
1745 _aotTimerES = IOTimerEventSource::timerEventSource(this,
1746 OSMemberFunctionCast(IOTimerEventSource::Action,
1747 this, &IOPMrootDomain::aotEvaluate));
1748 gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1749
1750 // Avoid publishing service early so gIOPMWorkLoop is
1751 // guaranteed to be initialized by rootDomain.
1752 publishPMRootDomain();
1753
1754 // create our power parent
1755 gPatriarch = new IORootParent;
1756 gPatriarch->init();
1757 gPatriarch->attach(this);
1758 gPatriarch->start(this);
1759 gPatriarch->addPowerChild(this);
1760
1761 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1762 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1763
1764 // install power change handler
1765 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1766
1767 #if DISPLAY_WRANGLER_PRESENT
1768 wranglerIdleSettings = OSDictionary::withCapacity(1);
1769 OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1770
1771 if (wranglerIdleSettings && wranglerIdlePeriod) {
1772 wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1773 wranglerIdlePeriod.get());
1774 }
1775
1776 #endif /* DISPLAY_WRANGLER_PRESENT */
1777
1778 lowLatencyAudioNotifierDict = OSDictionary::withCapacity(2);
1779 lowLatencyAudioNotifyStateSym = OSSymbol::withCString("LowLatencyAudioNotifyState");
1780 lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1781 lowLatencyAudioNotifyStateVal = OSNumber::withNumber(0ull, 32);
1782 lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64);
1783
1784 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1785 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1786 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1787 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1788 }
1789
1790 OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1791 setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1792
1793 // IOBacklightDisplay can take a long time to load at boot, or it may
1794 // not load at all if you're booting with clamshell closed. We publish
1795 // 'DisplayDims' here redundantly to get it published early and at all.
1796 OSSharedPtr<OSDictionary> matching;
1797 matching = serviceMatching("IOPMPowerSource");
1798 psIterator = getMatchingServices(matching.get());
1799
1800 if (psIterator && psIterator->getNextObject()) {
1801 // There's at least one battery on the system, so we publish
1802 // 'DisplayDims' support for the LCD.
1803 publishFeature("DisplayDims");
1804 }
1805
1806 // read swd_panic boot-arg
1807 PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1808 gWillShutdownSysctlRegistered = true;
1809
1810 #if HIBERNATION
1811 #if defined(__arm64__)
1812 #endif /* defined(__arm64__) */
1813 IOHibernateSystemInit(this);
1814 #endif
1815
1816 registerService(); // let clients find us
1817
1818 return true;
1819 }
1820
1821 //******************************************************************************
1822 // setProperties
1823 //
1824 // Receive a setProperty call
1825 // The "System Boot" property means the system is completely booted.
1826 //******************************************************************************
1827
1828 IOReturn
setProperties(OSObject * props_obj)1829 IOPMrootDomain::setProperties( OSObject * props_obj )
1830 {
1831 IOReturn return_value = kIOReturnSuccess;
1832 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
1833 OSBoolean *b = NULL;
1834 OSNumber *n = NULL;
1835 const OSSymbol *key = NULL;
1836 OSObject *obj = NULL;
1837 OSSharedPtr<OSCollectionIterator> iter;
1838
1839 if (!dict) {
1840 return kIOReturnBadArgument;
1841 }
1842
1843 bool clientEntitled = false;
1844 {
1845 OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1846 clientEntitled = (obj == kOSBooleanTrue);
1847 }
1848
1849 if (!clientEntitled) {
1850 const char * errorSuffix = NULL;
1851
1852 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1853 // That API can set 6 possible keys that are checked below.
1854 if ((dict->getCount() == 1) &&
1855 (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) ||
1856 dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) ||
1857 dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) ||
1858 dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) ||
1859 dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) ||
1860 dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) {
1861 return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
1862 if (return_value != kIOReturnSuccess) {
1863 errorSuffix = "privileged";
1864 }
1865 } else {
1866 return_value = kIOReturnNotPermitted;
1867 errorSuffix = "entitled";
1868 }
1869
1870 if (return_value != kIOReturnSuccess) {
1871 OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain);
1872 DLOG("%s failed, process %s is not %s\n", __func__,
1873 procName ? procName->getCStringNoCopy() : "", errorSuffix);
1874 return return_value;
1875 }
1876 }
1877
1878 OSSharedPtr<const OSSymbol> publish_simulated_battery_string = OSSymbol::withCString("SoftwareSimulatedBatteries");
1879 OSSharedPtr<const OSSymbol> boot_complete_string = OSSymbol::withCString("System Boot Complete");
1880 OSSharedPtr<const OSSymbol> sys_shutdown_string = OSSymbol::withCString("System Shutdown");
1881 OSSharedPtr<const OSSymbol> stall_halt_string = OSSymbol::withCString("StallSystemAtHalt");
1882 OSSharedPtr<const OSSymbol> battery_warning_disabled_string = OSSymbol::withCString("BatteryWarningsDisabled");
1883 OSSharedPtr<const OSSymbol> idle_seconds_string = OSSymbol::withCString("System Idle Seconds");
1884 OSSharedPtr<const OSSymbol> idle_milliseconds_string = OSSymbol::withCString("System Idle Milliseconds");
1885 OSSharedPtr<const OSSymbol> sleepdisabled_string = OSSymbol::withCString("SleepDisabled");
1886 OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1887 OSSharedPtr<const OSSymbol> loginwindow_progress_string = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1888 OSSharedPtr<const OSSymbol> coredisplay_progress_string = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1889 OSSharedPtr<const OSSymbol> coregraphics_progress_string = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1890 #if DEBUG || DEVELOPMENT
1891 OSSharedPtr<const OSSymbol> clamshell_close_string = OSSymbol::withCString("IOPMTestClamshellClose");
1892 OSSharedPtr<const OSSymbol> clamshell_open_string = OSSymbol::withCString("IOPMTestClamshellOpen");
1893 OSSharedPtr<const OSSymbol> ac_detach_string = OSSymbol::withCString("IOPMTestACDetach");
1894 OSSharedPtr<const OSSymbol> ac_attach_string = OSSymbol::withCString("IOPMTestACAttach");
1895 OSSharedPtr<const OSSymbol> desktopmode_set_string = OSSymbol::withCString("IOPMTestDesktopModeSet");
1896 OSSharedPtr<const OSSymbol> desktopmode_remove_string = OSSymbol::withCString("IOPMTestDesktopModeRemove");
1897 #endif
1898
1899 #if HIBERNATION
1900 OSSharedPtr<const OSSymbol> hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey);
1901 OSSharedPtr<const OSSymbol> hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey);
1902 OSSharedPtr<const OSSymbol> hibernatefilemin_string = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
1903 OSSharedPtr<const OSSymbol> hibernatefilemax_string = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
1904 OSSharedPtr<const OSSymbol> hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey);
1905 OSSharedPtr<const OSSymbol> hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey);
1906 #endif
1907
1908 iter = OSCollectionIterator::withCollection(dict);
1909 if (!iter) {
1910 return_value = kIOReturnNoMemory;
1911 goto exit;
1912 }
1913
1914 while ((key = (const OSSymbol *) iter->getNextObject()) &&
1915 (obj = dict->getObject(key))) {
1916 if (key->isEqualTo(publish_simulated_battery_string.get())) {
1917 if (OSDynamicCast(OSBoolean, obj)) {
1918 publishResource(key, kOSBooleanTrue);
1919 }
1920 } else if (key->isEqualTo(idle_seconds_string.get())) {
1921 if ((n = OSDynamicCast(OSNumber, obj))) {
1922 setProperty(key, n);
1923 idleMilliSeconds = n->unsigned32BitValue() * 1000;
1924 }
1925 } else if (key->isEqualTo(idle_milliseconds_string.get())) {
1926 if ((n = OSDynamicCast(OSNumber, obj))) {
1927 setProperty(key, n);
1928 idleMilliSeconds = n->unsigned32BitValue();
1929 }
1930 } else if (key->isEqualTo(boot_complete_string.get())) {
1931 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
1932 } else if (key->isEqualTo(sys_shutdown_string.get())) {
1933 if ((b = OSDynamicCast(OSBoolean, obj))) {
1934 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
1935 }
1936 } else if (key->isEqualTo(battery_warning_disabled_string.get())) {
1937 setProperty(key, obj);
1938 }
1939 #if HIBERNATION
1940 else if (key->isEqualTo(hibernatemode_string.get()) ||
1941 key->isEqualTo(hibernatefilemin_string.get()) ||
1942 key->isEqualTo(hibernatefilemax_string.get()) ||
1943 key->isEqualTo(hibernatefreeratio_string.get()) ||
1944 key->isEqualTo(hibernatefreetime_string.get())) {
1945 if ((n = OSDynamicCast(OSNumber, obj))) {
1946 setProperty(key, n);
1947 }
1948 } else if (key->isEqualTo(hibernatefile_string.get())) {
1949 OSString * str = OSDynamicCast(OSString, obj);
1950 if (str) {
1951 setProperty(key, str);
1952 }
1953 }
1954 #endif
1955 else if (key->isEqualTo(sleepdisabled_string.get())) {
1956 if ((b = OSDynamicCast(OSBoolean, obj))) {
1957 setProperty(key, b);
1958 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1959 }
1960 } else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
1961 obj->retain();
1962 pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
1963 } else if (key->isEqualTo(loginwindow_progress_string.get())) {
1964 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1965 uint32_t data = n->unsigned32BitValue();
1966 pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
1967 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
1968 }
1969 } else if (key->isEqualTo(coredisplay_progress_string.get())) {
1970 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1971 uint32_t data = n->unsigned32BitValue();
1972 pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
1973 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
1974 }
1975 } else if (key->isEqualTo(coregraphics_progress_string.get())) {
1976 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1977 uint32_t data = n->unsigned32BitValue();
1978 pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
1979 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
1980 }
1981 } else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
1982 key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
1983 key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
1984 key->isEqualTo(stall_halt_string.get())) {
1985 if ((b = OSDynamicCast(OSBoolean, obj))) {
1986 setProperty(key, b);
1987 }
1988 } else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
1989 key->isEqualTo(kIOPMDeepSleepTimerKey) ||
1990 key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
1991 key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
1992 if ((n = OSDynamicCast(OSNumber, obj))) {
1993 setProperty(key, n);
1994 }
1995 } else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
1996 if (kOSBooleanTrue == obj) {
1997 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
1998 } else {
1999 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2000 }
2001 DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
2002 }
2003 #if DEBUG || DEVELOPMENT
2004 else if (key->isEqualTo(clamshell_close_string.get())) {
2005 DLOG("SetProperties: setting clamshell close\n");
2006 UInt32 msg = kIOPMClamshellClosed;
2007 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2008 } else if (key->isEqualTo(clamshell_open_string.get())) {
2009 DLOG("SetProperties: setting clamshell open\n");
2010 UInt32 msg = kIOPMClamshellOpened;
2011 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2012 } else if (key->isEqualTo(ac_detach_string.get())) {
2013 DLOG("SetProperties: setting ac detach\n");
2014 UInt32 msg = kIOPMSetACAdaptorConnected;
2015 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2016 } else if (key->isEqualTo(ac_attach_string.get())) {
2017 DLOG("SetProperties: setting ac attach\n");
2018 UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue;
2019 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2020 } else if (key->isEqualTo(desktopmode_set_string.get())) {
2021 DLOG("SetProperties: setting desktopmode");
2022 UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue;
2023 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2024 } else if (key->isEqualTo(desktopmode_remove_string.get())) {
2025 DLOG("SetProperties: removing desktopmode\n");
2026 UInt32 msg = kIOPMSetDesktopMode;
2027 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2028 }
2029 #endif
2030 // Relay our allowed PM settings onto our registered PM clients
2031 else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
2032 return_value = setPMSetting(key, obj);
2033 if (kIOReturnSuccess != return_value) {
2034 break;
2035 }
2036 } else {
2037 DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
2038 }
2039 }
2040
2041 exit:
2042 return return_value;
2043 }
2044
2045 // MARK: -
2046 // MARK: Aggressiveness
2047
2048 //******************************************************************************
2049 // setAggressiveness
2050 //
2051 // Override IOService::setAggressiveness()
2052 //******************************************************************************
2053
2054 IOReturn
setAggressiveness(unsigned long type,unsigned long value)2055 IOPMrootDomain::setAggressiveness(
2056 unsigned long type,
2057 unsigned long value )
2058 {
2059 return setAggressiveness( type, value, 0 );
2060 }
2061
2062 /*
2063 * Private setAggressiveness() with an internal options argument.
2064 */
2065 IOReturn
setAggressiveness(unsigned long type,unsigned long value,IOOptionBits options)2066 IOPMrootDomain::setAggressiveness(
2067 unsigned long type,
2068 unsigned long value,
2069 IOOptionBits options )
2070 {
2071 AggressivesRequest * entry;
2072 AggressivesRequest * request;
2073 bool found = false;
2074
2075 if ((type > UINT_MAX) || (value > UINT_MAX)) {
2076 return kIOReturnBadArgument;
2077 }
2078
2079 if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2080 DLOG("setAggressiveness(%x) %s = %u\n",
2081 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2082 } else {
2083 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2084 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2085 }
2086
2087 request = IOMallocType(AggressivesRequest);
2088 request->options = options;
2089 request->dataType = kAggressivesRequestTypeRecord;
2090 request->data.record.type = (uint32_t) type;
2091 request->data.record.value = (uint32_t) value;
2092
2093 AGGRESSIVES_LOCK();
2094
2095 // Update disk quick spindown flag used by getAggressiveness().
2096 // Never merge requests with quick spindown flags set.
2097
2098 if (options & kAggressivesOptionQuickSpindownEnable) {
2099 gAggressivesState |= kAggressivesStateQuickSpindown;
2100 } else if (options & kAggressivesOptionQuickSpindownDisable) {
2101 gAggressivesState &= ~kAggressivesStateQuickSpindown;
2102 } else {
2103 // Coalesce requests with identical aggressives types.
2104 // Deal with callers that calls us too "aggressively".
2105
2106 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2107 {
2108 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2109 (entry->data.record.type == type) &&
2110 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2111 entry->data.record.value = (uint32_t) value;
2112 found = true;
2113 break;
2114 }
2115 }
2116 }
2117
2118 if (!found) {
2119 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2120 }
2121
2122 AGGRESSIVES_UNLOCK();
2123
2124 if (found) {
2125 IOFreeType(request, AggressivesRequest);
2126 }
2127
2128 if (options & kAggressivesOptionSynchronous) {
2129 handleAggressivesRequests(); // not truly synchronous
2130 } else {
2131 thread_call_enter(aggressivesThreadCall);
2132 }
2133
2134 return kIOReturnSuccess;
2135 }
2136
2137 //******************************************************************************
2138 // getAggressiveness
2139 //
2140 // Override IOService::setAggressiveness()
2141 // Fetch the aggressiveness factor with the given type.
2142 //******************************************************************************
2143
2144 IOReturn
getAggressiveness(unsigned long type,unsigned long * outLevel)2145 IOPMrootDomain::getAggressiveness(
2146 unsigned long type,
2147 unsigned long * outLevel )
2148 {
2149 uint32_t value = 0;
2150 int source = 0;
2151
2152 if (!outLevel || (type > UINT_MAX)) {
2153 return kIOReturnBadArgument;
2154 }
2155
2156 AGGRESSIVES_LOCK();
2157
2158 // Disk quick spindown in effect, report value = 1
2159
2160 if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2161 (type == kPMMinutesToSpinDown)) {
2162 value = kAggressivesMinValue;
2163 source = 1;
2164 }
2165
2166 // Consult the pending request queue.
2167
2168 if (!source) {
2169 AggressivesRequest * entry;
2170
2171 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2172 {
2173 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2174 (entry->data.record.type == type) &&
2175 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2176 value = entry->data.record.value;
2177 source = 2;
2178 break;
2179 }
2180 }
2181 }
2182
2183 // Consult the backend records.
2184
2185 if (!source && aggressivesData) {
2186 AggressivesRecord * record;
2187 int i, count;
2188
2189 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2190 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2191
2192 for (i = 0; i < count; i++, record++) {
2193 if (record->type == type) {
2194 value = record->value;
2195 source = 3;
2196 break;
2197 }
2198 }
2199 }
2200
2201 AGGRESSIVES_UNLOCK();
2202
2203 if (source) {
2204 *outLevel = (unsigned long) value;
2205 return kIOReturnSuccess;
2206 } else {
2207 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
2208 *outLevel = 0; // default return = 0, driver may not check for error
2209 return kIOReturnInvalid;
2210 }
2211 }
2212
2213 //******************************************************************************
2214 // joinAggressiveness
2215 //
2216 // Request from IOService to join future aggressiveness broadcasts.
2217 //******************************************************************************
2218
2219 IOReturn
joinAggressiveness(IOService * service)2220 IOPMrootDomain::joinAggressiveness(
2221 IOService * service )
2222 {
2223 AggressivesRequest * request;
2224
2225 if (!service || (service == this)) {
2226 return kIOReturnBadArgument;
2227 }
2228
2229 DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2230
2231 request = IOMallocType(AggressivesRequest);
2232 request->dataType = kAggressivesRequestTypeService;
2233 request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2234
2235 AGGRESSIVES_LOCK();
2236 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2237 AGGRESSIVES_UNLOCK();
2238
2239 thread_call_enter(aggressivesThreadCall);
2240
2241 return kIOReturnSuccess;
2242 }
2243
2244 //******************************************************************************
2245 // handleAggressivesRequests
2246 //
2247 // Backend thread processes all incoming aggressiveness requests in the queue.
2248 //******************************************************************************
2249
2250 static void
handleAggressivesFunction(thread_call_param_t param1,thread_call_param_t param2)2251 handleAggressivesFunction(
2252 thread_call_param_t param1,
2253 thread_call_param_t param2 )
2254 {
2255 if (param1) {
2256 ((IOPMrootDomain *) param1)->handleAggressivesRequests();
2257 }
2258 }
2259
2260 void
handleAggressivesRequests(void)2261 IOPMrootDomain::handleAggressivesRequests( void )
2262 {
2263 AggressivesRecord * start;
2264 AggressivesRecord * record;
2265 AggressivesRequest * request;
2266 queue_head_t joinedQueue;
2267 int i, count;
2268 bool broadcast;
2269 bool found;
2270 bool pingSelf = false;
2271
2272 AGGRESSIVES_LOCK();
2273
2274 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2275 queue_empty(&aggressivesQueue)) {
2276 goto unlock_done;
2277 }
2278
2279 gAggressivesState |= kAggressivesStateBusy;
2280 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2281 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2282
2283 do{
2284 broadcast = false;
2285 queue_init(&joinedQueue);
2286
2287 do{
2288 // Remove request from the incoming queue in FIFO order.
2289 queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
2290 switch (request->dataType) {
2291 case kAggressivesRequestTypeRecord:
2292 // Update existing record if found.
2293 found = false;
2294 for (i = 0, record = start; i < count; i++, record++) {
2295 if (record->type == request->data.record.type) {
2296 found = true;
2297
2298 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2299 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2300 broadcast = true;
2301 record->flags |= (kAggressivesRecordFlagMinValue |
2302 kAggressivesRecordFlagModified);
2303 DLOG("disk spindown accelerated, was %u min\n",
2304 record->value);
2305 }
2306 } else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2307 if (record->flags & kAggressivesRecordFlagMinValue) {
2308 broadcast = true;
2309 record->flags |= kAggressivesRecordFlagModified;
2310 record->flags &= ~kAggressivesRecordFlagMinValue;
2311 DLOG("disk spindown restored to %u min\n",
2312 record->value);
2313 }
2314 } else if (record->value != request->data.record.value) {
2315 record->value = request->data.record.value;
2316 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2317 broadcast = true;
2318 record->flags |= kAggressivesRecordFlagModified;
2319 }
2320 }
2321 break;
2322 }
2323 }
2324
2325 // No matching record, append a new record.
2326 if (!found &&
2327 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2328 AggressivesRecord newRecord;
2329
2330 newRecord.flags = kAggressivesRecordFlagModified;
2331 newRecord.type = request->data.record.type;
2332 newRecord.value = request->data.record.value;
2333 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2334 newRecord.flags |= kAggressivesRecordFlagMinValue;
2335 DLOG("disk spindown accelerated\n");
2336 }
2337
2338 aggressivesData->appendValue(newRecord);
2339
2340 // OSData may have switched to another (larger) buffer.
2341 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2342 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2343 broadcast = true;
2344 }
2345
2346 // Finished processing the request, release it.
2347 IOFreeType(request, AggressivesRequest);
2348 break;
2349
2350 case kAggressivesRequestTypeService:
2351 // synchronizeAggressives() will free request.
2352 queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2353 break;
2354
2355 default:
2356 panic("bad aggressives request type %x", request->dataType);
2357 break;
2358 }
2359 } while (!queue_empty(&aggressivesQueue));
2360
2361 // Release the lock to perform work, with busy flag set.
2362 if (!queue_empty(&joinedQueue) || broadcast) {
2363 AGGRESSIVES_UNLOCK();
2364 if (!queue_empty(&joinedQueue)) {
2365 synchronizeAggressives(&joinedQueue, start, count);
2366 }
2367 if (broadcast) {
2368 broadcastAggressives(start, count);
2369 }
2370 AGGRESSIVES_LOCK();
2371 }
2372
2373 // Remove the modified flag from all records.
2374 for (i = 0, record = start; i < count; i++, record++) {
2375 if ((record->flags & kAggressivesRecordFlagModified) &&
2376 ((record->type == kPMMinutesToDim) ||
2377 (record->type == kPMMinutesToSleep))) {
2378 pingSelf = true;
2379 }
2380
2381 record->flags &= ~kAggressivesRecordFlagModified;
2382 }
2383
2384 // Check the incoming queue again since new entries may have been
2385 // added while lock was released above.
2386 } while (!queue_empty(&aggressivesQueue));
2387
2388 gAggressivesState &= ~kAggressivesStateBusy;
2389
2390 unlock_done:
2391 AGGRESSIVES_UNLOCK();
2392
2393 // Root domain is interested in system and display sleep slider changes.
2394 // Submit a power event to handle those changes on the PM work loop.
2395
2396 if (pingSelf && pmPowerStateQueue) {
2397 pmPowerStateQueue->submitPowerEvent(
2398 kPowerEventPolicyStimulus,
2399 (void *) kStimulusAggressivenessChanged );
2400 }
2401 }
2402
2403 //******************************************************************************
2404 // synchronizeAggressives
2405 //
2406 // Push all known aggressiveness records to one or more IOService.
2407 //******************************************************************************
2408
2409 void
synchronizeAggressives(queue_head_t * joinedQueue,const AggressivesRecord * array,int count)2410 IOPMrootDomain::synchronizeAggressives(
2411 queue_head_t * joinedQueue,
2412 const AggressivesRecord * array,
2413 int count )
2414 {
2415 OSSharedPtr<IOService> service;
2416 AggressivesRequest * request;
2417 const AggressivesRecord * record;
2418 IOPMDriverCallEntry callEntry;
2419 uint32_t value;
2420 int i;
2421
2422 while (!queue_empty(joinedQueue)) {
2423 queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
2424 if (request->dataType == kAggressivesRequestTypeService) {
2425 // retained by joinAggressiveness(), so take ownership
2426 service = os::move(request->data.service);
2427 } else {
2428 service.reset();
2429 }
2430
2431 IOFreeType(request, AggressivesRequest);
2432 request = NULL;
2433
2434 if (service) {
2435 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2436 for (i = 0, record = array; i < count; i++, record++) {
2437 value = record->value;
2438 if (record->flags & kAggressivesRecordFlagMinValue) {
2439 value = kAggressivesMinValue;
2440 }
2441
2442 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2443 record->type, value, service->getName());
2444 service->setAggressiveness(record->type, value);
2445 }
2446 service->deassertPMDriverCall(&callEntry);
2447 }
2448 }
2449 }
2450 }
2451
2452 //******************************************************************************
2453 // broadcastAggressives
2454 //
2455 // Traverse PM tree and call setAggressiveness() for records that have changed.
2456 //******************************************************************************
2457
2458 void
broadcastAggressives(const AggressivesRecord * array,int count)2459 IOPMrootDomain::broadcastAggressives(
2460 const AggressivesRecord * array,
2461 int count )
2462 {
2463 OSSharedPtr<IORegistryIterator> iter;
2464 IORegistryEntry *entry;
2465 OSSharedPtr<IORegistryEntry> child;
2466 IOPowerConnection *connect;
2467 IOService *service;
2468 const AggressivesRecord *record;
2469 IOPMDriverCallEntry callEntry;
2470 uint32_t value;
2471 int i;
2472
2473 iter = IORegistryIterator::iterateOver(
2474 this, gIOPowerPlane, kIORegistryIterateRecursively);
2475 if (iter) {
2476 do{
2477 // !! reset the iterator
2478 iter->reset();
2479 while ((entry = iter->getNextObject())) {
2480 connect = OSDynamicCast(IOPowerConnection, entry);
2481 if (!connect || !connect->getReadyFlag()) {
2482 continue;
2483 }
2484
2485 child = connect->copyChildEntry(gIOPowerPlane);
2486 if (child) {
2487 if ((service = OSDynamicCast(IOService, child.get()))) {
2488 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2489 for (i = 0, record = array; i < count; i++, record++) {
2490 if (record->flags & kAggressivesRecordFlagModified) {
2491 value = record->value;
2492 if (record->flags & kAggressivesRecordFlagMinValue) {
2493 value = kAggressivesMinValue;
2494 }
2495 _LOG("broadcastAggressives %x = %u to %s\n",
2496 record->type, value, service->getName());
2497 service->setAggressiveness(record->type, value);
2498 }
2499 }
2500 service->deassertPMDriverCall(&callEntry);
2501 }
2502 }
2503 }
2504 }
2505 }while (!entry && !iter->isValid());
2506 }
2507 }
2508
2509 //*****************************************
2510 // stackshot on power button press
2511 // ***************************************
2512 static void
powerButtonDownCallout(thread_call_param_t us,thread_call_param_t)2513 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2514 {
2515 /* Power button pressed during wake
2516 * Take a stackshot
2517 */
2518 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2519 ((IOPMrootDomain *)us)->takeStackshot(false);
2520 }
2521
2522 static void
powerButtonUpCallout(thread_call_param_t us,thread_call_param_t)2523 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2524 {
2525 /* Power button released.
2526 * Delete any stackshot data
2527 */
2528 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2529 ((IOPMrootDomain *)us)->deleteStackshot();
2530 }
2531 //*************************************************************************
2532 //
2533
2534 // MARK: -
2535 // MARK: System Sleep
2536
2537 //******************************************************************************
2538 // startIdleSleepTimer
2539 //
2540 //******************************************************************************
2541
2542 void
startIdleSleepTimer(uint32_t inMilliSeconds)2543 IOPMrootDomain::startIdleSleepTimer( uint32_t inMilliSeconds )
2544 {
2545 AbsoluteTime deadline;
2546
2547 ASSERT_GATED();
2548 if (gNoIdleFlag) {
2549 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2550 return;
2551 }
2552 if (inMilliSeconds) {
2553 if (inMilliSeconds < kMinimumTimeBeforeIdleSleep) {
2554 AbsoluteTime now;
2555 uint64_t nsec_since_wake;
2556 uint64_t msec_since_wake;
2557
2558 // Adjust idle timer so it will not expire until atleast kMinimumTimeBeforeIdleSleep milliseconds
2559 // after the most recent AP wake.
2560 clock_get_uptime(&now);
2561 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2562 absolutetime_to_nanoseconds(now, &nsec_since_wake);
2563 msec_since_wake = nsec_since_wake / NSEC_PER_MSEC;
2564
2565 if (msec_since_wake < kMinimumTimeBeforeIdleSleep) {
2566 uint32_t newIdleTimer = kMinimumTimeBeforeIdleSleep - (uint32_t)msec_since_wake;
2567
2568 // Ensure that our new idle timer is not less than inMilliSeconds,
2569 // as we should only be increasing the timer duration, not decreasing it
2570 if (newIdleTimer > inMilliSeconds) {
2571 DLOG("startIdleSleepTimer increasing timeout from %u to %u\n", inMilliSeconds, newIdleTimer);
2572 inMilliSeconds = newIdleTimer;
2573 }
2574 }
2575 }
2576 clock_interval_to_deadline(inMilliSeconds, kMillisecondScale, &deadline);
2577 thread_call_enter_delayed(extraSleepTimer, deadline);
2578 idleSleepTimerPending = true;
2579 } else {
2580 thread_call_enter(extraSleepTimer);
2581 }
2582 DLOG("idle timer set for %u milliseconds\n", inMilliSeconds);
2583 }
2584
2585 //******************************************************************************
2586 // cancelIdleSleepTimer
2587 //
2588 //******************************************************************************
2589
2590 void
cancelIdleSleepTimer(void)2591 IOPMrootDomain::cancelIdleSleepTimer( void )
2592 {
2593 ASSERT_GATED();
2594 if (idleSleepTimerPending) {
2595 DLOG("idle timer cancelled\n");
2596 thread_call_cancel(extraSleepTimer);
2597 idleSleepTimerPending = false;
2598
2599 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2600 AbsoluteTime now;
2601 clock_usec_t microsecs;
2602 clock_get_uptime(&now);
2603 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2604 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
2605 if (assertOnWakeReport) {
2606 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2607 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2608 }
2609 }
2610 }
2611 }
2612
2613 //******************************************************************************
2614 // idleSleepTimerExpired
2615 //
2616 //******************************************************************************
2617
2618 static void
idleSleepTimerExpired(thread_call_param_t us,thread_call_param_t)2619 idleSleepTimerExpired(
2620 thread_call_param_t us, thread_call_param_t )
2621 {
2622 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2623 }
2624
2625 //******************************************************************************
2626 // handleSleepTimerExpiration
2627 //
2628 // The time between the sleep idle timeout and the next longest one has elapsed.
2629 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2630 //******************************************************************************
2631
2632 void
handleSleepTimerExpiration(void)2633 IOPMrootDomain::handleSleepTimerExpiration( void )
2634 {
2635 if (!gIOPMWorkLoop->inGate()) {
2636 gIOPMWorkLoop->runAction(
2637 OSMemberFunctionCast(IOWorkLoop::Action, this,
2638 &IOPMrootDomain::handleSleepTimerExpiration),
2639 this);
2640 return;
2641 }
2642
2643 DLOG("sleep timer expired\n");
2644 ASSERT_GATED();
2645
2646 idleSleepTimerPending = false;
2647 setQuickSpinDownTimeout();
2648 adjustPowerState(true);
2649 }
2650
2651 //******************************************************************************
2652 // getTimeToIdleSleep
2653 //
2654 // Returns number of milliseconds left before going into idle sleep.
2655 // Caller has to make sure that idle sleep is allowed at the time of calling
2656 // this function
2657 //******************************************************************************
2658
2659 uint32_t
getTimeToIdleSleep(void)2660 IOPMrootDomain::getTimeToIdleSleep( void )
2661 {
2662 AbsoluteTime now, lastActivityTime;
2663 uint64_t nanos;
2664 uint32_t minutesSinceUserInactive = 0;
2665 uint32_t sleepDelay = 0;
2666
2667 if (!idleSleepEnabled) {
2668 return 0xffffffff;
2669 }
2670
2671 if (userActivityTime) {
2672 lastActivityTime = userActivityTime;
2673 } else {
2674 lastActivityTime = userBecameInactiveTime;
2675 }
2676
2677 // Ignore any lastActivityTime that predates the last system wake.
2678 // The goal is to avoid a sudden idle sleep right after a dark wake
2679 // due to sleepDelay=0 computed below. The alternative 60s minimum
2680 // timeout should be large enough to allow dark wake to complete,
2681 // at which point the idle timer will be promptly cancelled.
2682 clock_get_uptime(&now);
2683 if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) &&
2684 (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) {
2685 SUB_ABSOLUTETIME(&now, &lastActivityTime);
2686 absolutetime_to_nanoseconds(now, &nanos);
2687 minutesSinceUserInactive = nanos / (60000000000ULL);
2688
2689 if (minutesSinceUserInactive >= sleepSlider) {
2690 sleepDelay = 0;
2691 } else {
2692 sleepDelay = sleepSlider - minutesSinceUserInactive;
2693 }
2694 } else {
2695 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2696 lastActivityTime, now, gIOLastWakeAbsTime);
2697 sleepDelay = sleepSlider;
2698 }
2699
2700 DLOG("user inactive %u min, time to idle sleep %u min\n",
2701 minutesSinceUserInactive, sleepDelay);
2702
2703 return sleepDelay * 60 * 1000;
2704 }
2705
2706 //******************************************************************************
2707 // setQuickSpinDownTimeout
2708 //
2709 //******************************************************************************
2710
2711 void
setQuickSpinDownTimeout(void)2712 IOPMrootDomain::setQuickSpinDownTimeout( void )
2713 {
2714 ASSERT_GATED();
2715 setAggressiveness(
2716 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2717 }
2718
2719 //******************************************************************************
2720 // restoreUserSpinDownTimeout
2721 //
2722 //******************************************************************************
2723
2724 void
restoreUserSpinDownTimeout(void)2725 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2726 {
2727 ASSERT_GATED();
2728 setAggressiveness(
2729 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2730 }
2731
2732 //******************************************************************************
2733 // sleepSystem
2734 //
2735 //******************************************************************************
2736
2737 /* public */
2738 IOReturn
sleepSystem(void)2739 IOPMrootDomain::sleepSystem( void )
2740 {
2741 return sleepSystemOptions(NULL);
2742 }
2743
2744 /* private */
2745 IOReturn
sleepSystemOptions(OSDictionary * options)2746 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2747 {
2748 OSObject *obj = NULL;
2749 OSString *reason = NULL;
2750 /* sleepSystem is a public function, and may be called by any kernel driver.
2751 * And that's bad - drivers should sleep the system by calling
2752 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2753 *
2754 * Note that user space app calls to IOPMSleepSystem() will also travel
2755 * this code path and thus be correctly identified as software sleeps.
2756 */
2757
2758 if (options && options->getObject("OSSwitch")) {
2759 // Log specific sleep cause for OS Switch hibernation
2760 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2761 }
2762
2763 if (options && (obj = options->getObject("Sleep Reason"))) {
2764 reason = OSDynamicCast(OSString, obj);
2765 if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2766 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2767 }
2768 if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2769 return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2770 }
2771 }
2772
2773 return privateSleepSystem( kIOPMSleepReasonSoftware);
2774 }
2775
2776 /* private */
2777 IOReturn
privateSleepSystem(uint32_t sleepReason)2778 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2779 {
2780 /* Called from both gated and non-gated context */
2781
2782 if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2783 return kIOReturnNotPermitted;
2784 }
2785
2786 pmPowerStateQueue->submitPowerEvent(
2787 kPowerEventPolicyStimulus,
2788 (void *) kStimulusDemandSystemSleep,
2789 sleepReason);
2790
2791 return kIOReturnSuccess;
2792 }
2793
2794 //******************************************************************************
2795 // powerChangeDone
2796 //
2797 // This overrides powerChangeDone in IOService.
2798 //******************************************************************************
2799 void
powerChangeDone(unsigned long previousPowerState)2800 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2801 {
2802 #if !__i386__ && !__x86_64__
2803 uint64_t timeSinceReset = 0;
2804 #endif
2805 uint64_t now;
2806 unsigned long newState;
2807 clock_sec_t secs;
2808 clock_usec_t microsecs;
2809 uint32_t lastDebugWakeSeconds;
2810 clock_sec_t adjWakeTime;
2811 IOPMCalendarStruct nowCalendar;
2812
2813 ASSERT_GATED();
2814 newState = getPowerState();
2815 DLOG("PowerChangeDone: %s->%s\n",
2816 getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2817
2818 if (previousPowerState == newState) {
2819 return;
2820 }
2821
2822 notifierThread = current_thread();
2823 switch (getPowerState()) {
2824 case SLEEP_STATE: {
2825 if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2826 secs = 0;
2827 microsecs = 0;
2828 PEGetUTCTimeOfDay(&secs, µsecs);
2829
2830 adjWakeTime = 0;
2831 if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) {
2832 IOLog("use _calendarWakeAlarmUTC\n");
2833 adjWakeTime = _calendarWakeAlarmUTC;
2834 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
2835 IOLog("accelerate _aotWakeTime for exit\n");
2836 adjWakeTime = secs;
2837 } else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2838 IOLog("accelerate _aotWakeTime for assertion\n");
2839 adjWakeTime = secs;
2840 }
2841 if (adjWakeTime) {
2842 IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2843 }
2844
2845 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2846 IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2847
2848 IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2849 assert(kIOReturnSuccess == ret);
2850 }
2851 if (_aotLastWakeTime) {
2852 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
2853 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
2854 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
2855 gWakeReasonString,
2856 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2857 }
2858 }
2859 _aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2860 if (_aotTimerScheduled) {
2861 _aotTimerES->cancelTimeout();
2862 _aotTimerScheduled = false;
2863 }
2864 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2865
2866 // re-enable this timer for next sleep
2867 cancelIdleSleepTimer();
2868
2869 if (clamshellExists) {
2870 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
2871 if (gClamshellFlags & kClamshell_WAR_58009435) {
2872 // Disable clamshell sleep until system has completed full wake.
2873 // This prevents a system sleep request (due to a clamshell close)
2874 // from being queued until the end of system full wake - even if
2875 // other clamshell disable bits outside of our control is wrong.
2876 setClamShellSleepDisable(true, kClamshellSleepDisableInternal);
2877 }
2878 #endif
2879
2880 // Log the last known clamshell state before system sleep
2881 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
2882 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask,
2883 desktopMode, acAdaptorConnected);
2884 }
2885
2886 clock_get_calendar_absolute_and_microtime(&secs, µsecs, &now);
2887 logtime(secs);
2888 gIOLastSleepTime.tv_sec = secs;
2889 gIOLastSleepTime.tv_usec = microsecs;
2890 if (!_aotLastWakeTime) {
2891 gIOLastUserSleepTime = gIOLastSleepTime;
2892 }
2893
2894 gIOLastWakeTime.tv_sec = 0;
2895 gIOLastWakeTime.tv_usec = 0;
2896 gIOLastSleepAbsTime = now;
2897
2898 if (wake2DarkwakeDelay && sleepDelaysReport) {
2899 clock_sec_t wake2DarkwakeSecs, darkwake2SleepSecs;
2900 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2901
2902 SUB_ABSOLUTETIME(&now, &ts_sleepStart);
2903 absolutetime_to_microtime(now, &darkwake2SleepSecs, µsecs);
2904 absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, µsecs);
2905 HISTREPORT_TALLYVALUE(sleepDelaysReport,
2906 (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
2907
2908 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
2909 wake2DarkwakeDelay = 0;
2910 }
2911 #if HIBERNATION
2912 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2913 #if (DEVELOPMENT || DEBUG)
2914 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2915 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2916 "System State",
2917 gIOHibernateState ? "Enter Hibernate" : "Enter Sleep"
2918 );
2919 #endif /* DEVELOPMENT || DEBUG */
2920 IOHibernateSystemHasSlept();
2921
2922 evaluateSystemSleepPolicyFinal();
2923 #else
2924 LOG("System Sleep\n");
2925 #if (DEVELOPMENT || DEBUG)
2926 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2927 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2928 "System State", "Enter Sleep");
2929 #endif /* DEVELOPMENT || DEBUG */
2930 #endif
2931 if (thermalWarningState) {
2932 OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
2933 if (event) {
2934 systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
2935 }
2936 }
2937 assertOnWakeSecs = 0;
2938 lowBatteryCondition = false;
2939 thermalEmergencyState = false;
2940
2941 #if DEVELOPMENT || DEBUG
2942 extern int g_should_log_clock_adjustments;
2943 if (g_should_log_clock_adjustments) {
2944 clock_sec_t secs = 0;
2945 clock_usec_t microsecs = 0;
2946 uint64_t now_b = mach_absolute_time();
2947
2948 secs = 0;
2949 microsecs = 0;
2950 PEGetUTCTimeOfDay(&secs, µsecs);
2951
2952 uint64_t now_a = mach_absolute_time();
2953 os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2954 __func__, (unsigned long)secs, microsecs, now_b, now_a);
2955 }
2956 #endif
2957
2958 getPlatform()->sleepKernel();
2959
2960 // The CPU(s) are off at this point,
2961 // Code will resume execution here upon wake.
2962
2963 clock_get_uptime(&gIOLastWakeAbsTime);
2964 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
2965 #if DEVELOPMENT || DEBUG
2966 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2967 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2968 "System State", "Waking Up"
2969 );
2970 #endif /* DEVELOPMENT || DEBUG */
2971 _highestCapability = 0;
2972
2973 #if HIBERNATION
2974 IOHibernateSystemWake();
2975 #endif
2976
2977 // sleep transition complete
2978 gSleepOrShutdownPending = 0;
2979
2980 // trip the reset of the calendar clock
2981 clock_wakeup_calendar();
2982 clock_get_calendar_microtime(&secs, µsecs);
2983 gIOLastWakeTime.tv_sec = secs;
2984 gIOLastWakeTime.tv_usec = microsecs;
2985
2986 // aot
2987 if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
2988 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
2989 secs = 0;
2990 microsecs = 0;
2991 PEGetUTCTimeOfDay(&secs, µsecs);
2992 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2993 IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2994 _aotMetrics->sleepCount++;
2995 _aotLastWakeTime = gIOLastWakeAbsTime;
2996 if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
2997 _aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
2998 = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
2999 _aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
3000 = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
3001 }
3002
3003 if (_aotTestTime) {
3004 if (_aotWakeTimeUTC <= secs) {
3005 _aotTestTime = _aotTestTime + _aotTestInterval;
3006 }
3007 setWakeTime(_aotTestTime);
3008 }
3009 }
3010
3011 #if HIBERNATION
3012 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
3013 #endif
3014
3015 lastSleepReason = 0;
3016
3017 lastDebugWakeSeconds = _debugWakeSeconds;
3018 _debugWakeSeconds = 0;
3019 _scheduledAlarmMask = 0;
3020 _nextScheduledAlarmType = NULL;
3021
3022 darkWakeExit = false;
3023 darkWakePowerClamped = false;
3024 darkWakePostTickle = false;
3025 darkWakeHibernateError = false;
3026 darkWakeToSleepASAP = true;
3027 darkWakeLogClamp = true;
3028 sleepTimerMaintenance = false;
3029 sleepToStandby = false;
3030 wranglerTickled = false;
3031 userWasActive = false;
3032 isRTCAlarmWake = false;
3033 clamshellIgnoreClose = false;
3034 fullWakeReason = kFullWakeReasonNone;
3035
3036 #if defined(__i386__) || defined(__x86_64__)
3037 kdebugTrace(kPMLogSystemWake, 0, 0, 0);
3038
3039 OSSharedPtr<OSObject> wakeTypeProp = copyProperty(kIOPMRootDomainWakeTypeKey);
3040 OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey);
3041 OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get());
3042 OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get());
3043
3044 if (wakeReason && (wakeReason->getLength() >= 2) &&
3045 gWakeReasonString[0] == '\0') {
3046 WAKEEVENT_LOCK();
3047 // Until the platform driver can claim its wake reasons
3048 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
3049 sizeof(gWakeReasonString));
3050 if (!gWakeReasonSysctlRegistered) {
3051 gWakeReasonSysctlRegistered = true;
3052 }
3053 WAKEEVENT_UNLOCK();
3054 }
3055
3056 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
3057 lowBatteryCondition = true;
3058 darkWakeMaintenance = true;
3059 } else {
3060 #if HIBERNATION
3061 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3062 OSNumber * hibOptions = OSDynamicCast( OSNumber, hibOptionsProp.get());
3063 if (hibernateAborted || ((hibOptions &&
3064 !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
3065 // Hibernate aborted, or EFI brought up graphics
3066 darkWakeExit = true;
3067 if (hibernateAborted) {
3068 DLOG("Hibernation aborted\n");
3069 } else {
3070 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
3071 }
3072 } else
3073 #endif
3074 if (wakeType && (
3075 wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
3076 wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
3077 // User wake or RTC alarm
3078 darkWakeExit = true;
3079 if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
3080 isRTCAlarmWake = true;
3081 }
3082 } else if (wakeType &&
3083 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
3084 // SMC standby timer trumps SleepX
3085 darkWakeMaintenance = true;
3086 sleepTimerMaintenance = true;
3087 } else if ((lastDebugWakeSeconds != 0) &&
3088 ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
3089 // SleepX before maintenance
3090 darkWakeExit = true;
3091 } else if (wakeType &&
3092 wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
3093 darkWakeMaintenance = true;
3094 } else if (wakeType &&
3095 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
3096 darkWakeMaintenance = true;
3097 darkWakeSleepService = true;
3098 #if HIBERNATION
3099 if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3100 sleepToStandby = true;
3101 }
3102 #endif
3103 } else if (wakeType &&
3104 wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3105 darkWakeMaintenance = true;
3106 darkWakeHibernateError = true;
3107 } else {
3108 // Unidentified wake source, resume to full wake if debug
3109 // alarm is pending.
3110
3111 if (lastDebugWakeSeconds &&
3112 (!wakeReason || wakeReason->isEqualTo(""))) {
3113 darkWakeExit = true;
3114 }
3115 }
3116 }
3117
3118 if (darkWakeExit) {
3119 darkWakeToSleepASAP = false;
3120 fullWakeReason = kFullWakeReasonLocalUser;
3121 reportUserInput();
3122 } else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
3123 handleSetDisplayPowerOn(true);
3124 } else if (!darkWakeMaintenance) {
3125 // Early/late tickle for non-maintenance wake.
3126 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) {
3127 darkWakePostTickle = true;
3128 }
3129 }
3130 #else /* !__i386__ && !__x86_64__ */
3131 timeSinceReset = ml_get_time_since_reset();
3132 kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3133
3134 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) {
3135 wranglerTickled = true;
3136 fullWakeReason = kFullWakeReasonLocalUser;
3137 requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3138 } else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
3139 isRTCAlarmWake = true;
3140 fullWakeReason = kFullWakeReasonLocalUser;
3141 requestUserActive(this, "RTC debug alarm");
3142 } else {
3143 #if HIBERNATION
3144 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3145 OSNumber * hibOptions = OSDynamicCast(OSNumber, hibOptionsProp.get());
3146 if (hibOptions && !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)) {
3147 fullWakeReason = kFullWakeReasonLocalUser;
3148 requestUserActive(this, "hibernate user wake");
3149 }
3150 #endif
3151 }
3152
3153 // stay awake for at least 30 seconds
3154 startIdleSleepTimer(30 * 1000);
3155 #endif
3156 sleepCnt++;
3157
3158 thread_call_enter(updateConsoleUsersEntry);
3159
3160 // Skip AOT_STATE if we are waking up from an RTC timer.
3161 // This check needs to be done after the epoch change is processed
3162 // and before the changePowerStateWithTagToPriv() call below.
3163 WAKEEVENT_LOCK();
3164 aotShouldExit(false, false);
3165 WAKEEVENT_UNLOCK();
3166
3167 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
3168 break;
3169 }
3170 #if !__i386__ && !__x86_64__
3171 case ON_STATE:
3172 case AOT_STATE:
3173 {
3174 DLOG("Force re-evaluating aggressiveness\n");
3175 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3176 pmPowerStateQueue->submitPowerEvent(
3177 kPowerEventPolicyStimulus,
3178 (void *) kStimulusNoIdleSleepPreventers );
3179
3180 // After changing to ON_STATE, invalidate any previously queued
3181 // request to change to a state less than ON_STATE. This isn't
3182 // necessary for AOT_STATE or if the device has only one running
3183 // state since the changePowerStateToPriv() issued at the tail
3184 // end of SLEEP_STATE case should take care of that.
3185 if (getPowerState() == ON_STATE) {
3186 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake);
3187 }
3188 break;
3189 }
3190 #endif /* !__i386__ && !__x86_64__ */
3191 }
3192 notifierThread = NULL;
3193 }
3194
3195 //******************************************************************************
3196 // requestPowerDomainState
3197 //
3198 // Extend implementation in IOService. Running on PM work loop thread.
3199 //******************************************************************************
3200
3201 IOReturn
requestPowerDomainState(IOPMPowerFlags childDesire,IOPowerConnection * childConnection,unsigned long specification)3202 IOPMrootDomain::requestPowerDomainState(
3203 IOPMPowerFlags childDesire,
3204 IOPowerConnection * childConnection,
3205 unsigned long specification )
3206 {
3207 // Idle and system sleep prevention flags affects driver desire.
3208 // Children desire are irrelevant so they are cleared.
3209
3210 return super::requestPowerDomainState(0, childConnection, specification);
3211 }
3212
3213
3214 static void
makeSleepPreventersListLog(const OSSharedPtr<OSSet> & preventers,char * buf,size_t buf_size)3215 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3216 {
3217 if (!preventers->getCount()) {
3218 return;
3219 }
3220
3221 char *buf_iter = buf + strlen(buf);
3222 char *buf_end = buf + buf_size;
3223
3224 OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3225 OSObject *obj = NULL;
3226
3227 while ((obj = iterator->getNextObject())) {
3228 IOService *srv = OSDynamicCast(IOService, obj);
3229 if (buf_iter < buf_end) {
3230 buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName());
3231 } else {
3232 DLOG("Print buffer exhausted for sleep preventers list\n");
3233 break;
3234 }
3235 }
3236 }
3237
3238 //******************************************************************************
3239 // updatePreventIdleSleepList
3240 //
3241 // Called by IOService on PM work loop.
3242 // Returns true if PM policy recognized the driver's desire to prevent idle
3243 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3244 //******************************************************************************
3245
3246 bool
updatePreventIdleSleepList(IOService * service,bool addNotRemove)3247 IOPMrootDomain::updatePreventIdleSleepList(
3248 IOService * service, bool addNotRemove)
3249 {
3250 unsigned int oldCount;
3251
3252 oldCount = idleSleepPreventersCount();
3253 return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3254 }
3255
3256 bool
updatePreventIdleSleepListInternal(IOService * service,bool addNotRemove,unsigned int oldCount)3257 IOPMrootDomain::updatePreventIdleSleepListInternal(
3258 IOService * service, bool addNotRemove, unsigned int oldCount)
3259 {
3260 unsigned int newCount;
3261
3262 ASSERT_GATED();
3263
3264 #if defined(XNU_TARGET_OS_OSX)
3265 // Only the display wrangler and no-idle-sleep kernel assertions
3266 // can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3267 // reported by drivers in their power state table is ignored.
3268 if (service && (service != wrangler) && (service != this)) {
3269 return false;
3270 }
3271 #endif
3272
3273 if (service) {
3274 if (addNotRemove) {
3275 preventIdleSleepList->setObject(service);
3276 DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3277 service->getName(), preventIdleSleepList->getCount());
3278 } else if (preventIdleSleepList->member(service)) {
3279 preventIdleSleepList->removeObject(service);
3280 DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3281 service->getName(), preventIdleSleepList->getCount());
3282 }
3283
3284 if (preventIdleSleepList->getCount()) {
3285 char buf[256] = "Idle Sleep Preventers:";
3286 makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3287 DLOG("%s\n", buf);
3288 }
3289 }
3290
3291 newCount = idleSleepPreventersCount();
3292
3293 if ((oldCount == 0) && (newCount != 0)) {
3294 // Driver added to empty prevent list.
3295 // Update the driver desire to prevent idle sleep.
3296 // Driver desire does not prevent demand sleep.
3297
3298 changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent);
3299 } else if ((oldCount != 0) && (newCount == 0)) {
3300 // Last driver removed from prevent list.
3301 // Drop the driver clamp to allow idle sleep.
3302
3303 changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3304 evaluatePolicy( kStimulusNoIdleSleepPreventers );
3305 }
3306 messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3307 &newCount, sizeof(newCount));
3308
3309 #if defined(XNU_TARGET_OS_OSX)
3310 if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
3311 DLOG("Cannot cancel idle sleep\n");
3312 return false; // do not idle-cancel
3313 }
3314 #endif
3315
3316 return true;
3317 }
3318
3319 //******************************************************************************
3320 // startSpinDump
3321 //******************************************************************************
3322
3323 void
startSpinDump(uint32_t spindumpKind)3324 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3325 {
3326 messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3327 }
3328
3329 //******************************************************************************
3330 // preventSystemSleepListUpdate
3331 //
3332 // Called by IOService on PM work loop.
3333 //******************************************************************************
3334
3335 void
updatePreventSystemSleepList(IOService * service,bool addNotRemove)3336 IOPMrootDomain::updatePreventSystemSleepList(
3337 IOService * service, bool addNotRemove )
3338 {
3339 unsigned int oldCount, newCount;
3340
3341 ASSERT_GATED();
3342 if (this == service) {
3343 return;
3344 }
3345
3346 oldCount = preventSystemSleepList->getCount();
3347 if (addNotRemove) {
3348 preventSystemSleepList->setObject(service);
3349 DLOG("Added %s to system sleep preventers list (Total %u)\n",
3350 service->getName(), preventSystemSleepList->getCount());
3351 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
3352 AbsoluteTime now;
3353 clock_usec_t microsecs;
3354 clock_get_uptime(&now);
3355 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3356 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
3357 if (assertOnWakeReport) {
3358 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3359 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3360 }
3361 }
3362 } else if (preventSystemSleepList->member(service)) {
3363 preventSystemSleepList->removeObject(service);
3364 DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3365 service->getName(), preventSystemSleepList->getCount());
3366
3367 if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
3368 // Lost all system sleep preventers.
3369 // Send stimulus if system sleep was blocked, and is in dark wake.
3370 evaluatePolicy( kStimulusDarkWakeEvaluate );
3371 }
3372 }
3373
3374 newCount = preventSystemSleepList->getCount();
3375 if (newCount) {
3376 char buf[256] = "System Sleep Preventers:";
3377 makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3378 DLOG("%s\n", buf);
3379 }
3380
3381 messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3382 &newCount, sizeof(newCount));
3383 }
3384
3385 void
copySleepPreventersList(OSArray ** idleSleepList,OSArray ** systemSleepList)3386 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3387 {
3388 OSSharedPtr<OSCollectionIterator> iterator;
3389 OSObject *object = NULL;
3390 OSSharedPtr<OSArray> array;
3391
3392 if (!gIOPMWorkLoop->inGate()) {
3393 gIOPMWorkLoop->runAction(
3394 OSMemberFunctionCast(IOWorkLoop::Action, this,
3395 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3396 this, (void *)idleSleepList, (void *)systemSleepList);
3397 return;
3398 }
3399
3400 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3401 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3402 array = OSArray::withCapacity(5);
3403
3404 if (iterator && array) {
3405 while ((object = iterator->getNextObject())) {
3406 IOService *service = OSDynamicCast(IOService, object);
3407 if (service) {
3408 OSSharedPtr<const OSSymbol> name = service->copyName();
3409 if (name) {
3410 array->setObject(name.get());
3411 }
3412 }
3413 }
3414 }
3415 *idleSleepList = array.detach();
3416 }
3417
3418 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3419 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3420 array = OSArray::withCapacity(5);
3421
3422 if (iterator && array) {
3423 while ((object = iterator->getNextObject())) {
3424 IOService *service = OSDynamicCast(IOService, object);
3425 if (service) {
3426 OSSharedPtr<const OSSymbol> name = service->copyName();
3427 if (name) {
3428 array->setObject(name.get());
3429 }
3430 }
3431 }
3432 }
3433 *systemSleepList = array.detach();
3434 }
3435 }
3436
3437 void
copySleepPreventersListWithID(OSArray ** idleSleepList,OSArray ** systemSleepList)3438 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3439 {
3440 OSSharedPtr<OSCollectionIterator> iterator;
3441 OSObject *object = NULL;
3442 OSSharedPtr<OSArray> array;
3443
3444 if (!gIOPMWorkLoop->inGate()) {
3445 gIOPMWorkLoop->runAction(
3446 OSMemberFunctionCast(IOWorkLoop::Action, this,
3447 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3448 this, (void *)idleSleepList, (void *)systemSleepList);
3449 return;
3450 }
3451
3452 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3453 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3454 array = OSArray::withCapacity(5);
3455
3456 if (iterator && array) {
3457 while ((object = iterator->getNextObject())) {
3458 IOService *service = OSDynamicCast(IOService, object);
3459 if (service) {
3460 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3461 OSSharedPtr<const OSSymbol> name = service->copyName();
3462 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3463 if (dict && name && id) {
3464 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3465 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3466 array->setObject(dict.get());
3467 }
3468 }
3469 }
3470 }
3471 *idleSleepList = array.detach();
3472 }
3473
3474 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3475 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3476 array = OSArray::withCapacity(5);
3477
3478 if (iterator && array) {
3479 while ((object = iterator->getNextObject())) {
3480 IOService *service = OSDynamicCast(IOService, object);
3481 if (service) {
3482 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3483 OSSharedPtr<const OSSymbol> name = service->copyName();
3484 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3485 if (dict && name && id) {
3486 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3487 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3488 array->setObject(dict.get());
3489 }
3490 }
3491 }
3492 }
3493 *systemSleepList = array.detach();
3494 }
3495 }
3496
3497 //******************************************************************************
3498 // tellChangeDown
3499 //
3500 // Override the superclass implementation to send a different message type.
3501 //******************************************************************************
3502
3503 bool
tellChangeDown(unsigned long stateNum)3504 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3505 {
3506 DLOG("tellChangeDown %s->%s\n",
3507 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3508
3509 if (SLEEP_STATE == stateNum) {
3510 // Legacy apps were already told in the full->dark transition
3511 if (!ignoreTellChangeDown) {
3512 tracePoint( kIOPMTracePointSleepApplications );
3513 } else {
3514 tracePoint( kIOPMTracePointSleepPriorityClients );
3515 }
3516 }
3517
3518 if (!ignoreTellChangeDown) {
3519 userActivityAtSleep = userActivityCount;
3520 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3521
3522 if (SLEEP_STATE == stateNum) {
3523 hibernateAborted = false;
3524
3525 // Direct callout into OSKext so it can disable kext unloads
3526 // during sleep/wake to prevent deadlocks.
3527 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3528
3529 IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3530
3531 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3532 // But tellClientsWithResponse() must be called for both.
3533 ignoreTellChangeDown = true;
3534 }
3535 }
3536
3537 return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3538 }
3539
3540 //******************************************************************************
3541 // askChangeDown
3542 //
3543 // Override the superclass implementation to send a different message type.
3544 // This must be idle sleep since we don't ask during any other power change.
3545 //******************************************************************************
3546
3547 bool
askChangeDown(unsigned long stateNum)3548 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3549 {
3550 DLOG("askChangeDown %s->%s\n",
3551 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3552
3553 // Don't log for dark wake entry
3554 if (kSystemTransitionSleep == _systemTransitionType) {
3555 tracePoint( kIOPMTracePointSleepApplications );
3556 }
3557
3558 return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3559 }
3560
3561 //******************************************************************************
3562 // askChangeDownDone
3563 //
3564 // An opportunity for root domain to cancel the power transition,
3565 // possibily due to an assertion created by powerd in response to
3566 // kIOMessageCanSystemSleep.
3567 //
3568 // Idle sleep:
3569 // full -> dark wake transition
3570 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3571 // 2. askChangeDownDone()
3572 // dark -> sleep transition
3573 // 1. Notify powerd with kIOMessageCanSystemSleep
3574 // 2. askChangeDownDone()
3575 //
3576 // Demand sleep:
3577 // full -> dark wake transition
3578 // 1. Notify powerd with kIOMessageCanSystemSleep
3579 // 2. askChangeDownDone()
3580 // dark -> sleep transition
3581 // 1. Notify powerd with kIOMessageCanSystemSleep
3582 // 2. askChangeDownDone()
3583 //******************************************************************************
3584
3585 void
askChangeDownDone(IOPMPowerChangeFlags * inOutChangeFlags,bool * cancel)3586 IOPMrootDomain::askChangeDownDone(
3587 IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3588 {
3589 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3590 *inOutChangeFlags, *cancel,
3591 _systemTransitionType,
3592 _currentCapability, _pendingCapability);
3593
3594 if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
3595 // Dark->Sleep transition.
3596 // Check if there are any deny sleep assertions.
3597 // lastSleepReason already set by handleOurPowerChangeStart()
3598
3599 if (!checkSystemCanSleep(lastSleepReason)) {
3600 // Cancel dark wake to sleep transition.
3601 // Must re-scan assertions upon entering dark wake.
3602
3603 *cancel = true;
3604 DLOG("cancel dark->sleep\n");
3605 }
3606 if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3607 uint64_t now = mach_continuous_time();
3608 if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3609 && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3610 *cancel = true;
3611 IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3612 }
3613 }
3614 }
3615 }
3616
3617 //******************************************************************************
3618 // systemDidNotSleep
3619 //
3620 // Work common to both canceled or aborted sleep.
3621 //******************************************************************************
3622
3623 void
systemDidNotSleep(void)3624 IOPMrootDomain::systemDidNotSleep( void )
3625 {
3626 // reset console lock state
3627 thread_call_enter(updateConsoleUsersEntry);
3628
3629 if (idleSleepEnabled) {
3630 if (!wrangler) {
3631 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3632 startIdleSleepTimer(kIdleSleepRetryInterval);
3633 #else
3634 startIdleSleepTimer(idleMilliSeconds);
3635 #endif
3636 } else if (!userIsActive) {
3637 // Manually start the idle sleep timer besides waiting for
3638 // the user to become inactive.
3639 startIdleSleepTimer(kIdleSleepRetryInterval);
3640 }
3641 }
3642
3643 preventTransitionToUserActive(false);
3644 IOService::setAdvisoryTickleEnable( true );
3645
3646 // After idle revert and cancel, send a did-change message to powerd
3647 // to balance the previous will-change message. Kernel clients do not
3648 // need this since sleep cannot be canceled once they are notified.
3649
3650 if (toldPowerdCapWillChange && systemCapabilityNotifier &&
3651 (_pendingCapability != _currentCapability) &&
3652 ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
3653 // Differs from a real capability gain change where notifyRef != 0,
3654 // but it is zero here since no response is expected.
3655
3656 IOPMSystemCapabilityChangeParameters params;
3657
3658 bzero(¶ms, sizeof(params));
3659 params.fromCapabilities = _pendingCapability;
3660 params.toCapabilities = _currentCapability;
3661 params.changeFlags = kIOPMSystemCapabilityDidChange;
3662
3663 DLOG("MESG cap %x->%x did change\n",
3664 params.fromCapabilities, params.toCapabilities);
3665 messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3666 ¶ms, sizeof(params));
3667 }
3668 }
3669
3670 //******************************************************************************
3671 // tellNoChangeDown
3672 //
3673 // Notify registered applications and kernel clients that we are not dropping
3674 // power.
3675 //
3676 // We override the superclass implementation so we can send a different message
3677 // type to the client or application being notified.
3678 //
3679 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3680 //******************************************************************************
3681
3682 void
tellNoChangeDown(unsigned long stateNum)3683 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3684 {
3685 DLOG("tellNoChangeDown %s->%s\n",
3686 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3687
3688 // Sleep canceled, clear the sleep trace point.
3689 tracePoint(kIOPMTracePointSystemUp);
3690
3691 systemDidNotSleep();
3692 return tellClients( kIOMessageSystemWillNotSleep );
3693 }
3694
3695 //******************************************************************************
3696 // tellChangeUp
3697 //
3698 // Notify registered applications and kernel clients that we are raising power.
3699 //
3700 // We override the superclass implementation so we can send a different message
3701 // type to the client or application being notified.
3702 //******************************************************************************
3703
3704 void
tellChangeUp(unsigned long stateNum)3705 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3706 {
3707 DLOG("tellChangeUp %s->%s\n",
3708 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3709
3710 ignoreTellChangeDown = false;
3711
3712 if (stateNum == ON_STATE) {
3713 // Direct callout into OSKext so it can disable kext unloads
3714 // during sleep/wake to prevent deadlocks.
3715 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3716
3717 // Notify platform that sleep was cancelled or resumed.
3718 getPlatform()->callPlatformFunction(
3719 sleepMessagePEFunction.get(), false,
3720 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3721 NULL, NULL, NULL);
3722
3723 if (getPowerState() == ON_STATE) {
3724 // Sleep was cancelled by idle cancel or revert
3725 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
3726 // rdar://problem/50363791
3727 // If system is in dark wake and sleep is cancelled, do not
3728 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3729 // priority clients. They haven't yet seen a SystemWillSleep
3730 // message before the cancellation. So make sure the kernel
3731 // client bit is cleared in _systemMessageClientMask before
3732 // invoking the tellClients() below. This bit may have been
3733 // set by handleOurPowerChangeStart() anticipating a successful
3734 // sleep and setting the filter mask ahead of time allows the
3735 // SystemWillSleep message to go through.
3736 _systemMessageClientMask &= ~kSystemMessageClientKernel;
3737 }
3738
3739 systemDidNotSleep();
3740 tellClients( kIOMessageSystemWillPowerOn );
3741 }
3742
3743 tracePoint( kIOPMTracePointWakeApplications );
3744 tellClients( kIOMessageSystemHasPoweredOn );
3745 } else if (stateNum == AOT_STATE) {
3746 if (getPowerState() == AOT_STATE) {
3747 // Sleep was cancelled by idle cancel or revert
3748 startIdleSleepTimer(idleMilliSeconds);
3749 }
3750 }
3751 }
3752
3753 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3754 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3755 ((params)->fromCapabilities & (flag)) && \
3756 (((params)->toCapabilities & (flag)) == 0))
3757
3758 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3759 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3760 ((params)->toCapabilities & (flag)) && \
3761 (((params)->fromCapabilities & (flag)) == 0))
3762
3763 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3764 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3765 ((params)->fromCapabilities & (flag)) && \
3766 (((params)->toCapabilities & (flag)) == 0))
3767
3768 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3769 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3770 ((params)->toCapabilities & (flag)) && \
3771 (((params)->fromCapabilities & (flag)) == 0))
3772
3773 //******************************************************************************
3774 // sysPowerDownHandler
3775 //
3776 // Perform a vfs sync before system sleep.
3777 //******************************************************************************
3778
3779 IOReturn
sysPowerDownHandler(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgs,vm_size_t argSize)3780 IOPMrootDomain::sysPowerDownHandler(
3781 void * target, void * refCon,
3782 UInt32 messageType, IOService * service,
3783 void * messageArgs, vm_size_t argSize )
3784 {
3785 static UInt32 lastSystemMessageType = 0;
3786 IOReturn ret = 0;
3787
3788 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3789
3790 // rdar://problem/50363791
3791 // Sanity check to make sure the SystemWill/Has message types are
3792 // received in the expected order for all kernel priority clients.
3793 if (messageType == kIOMessageSystemWillSleep ||
3794 messageType == kIOMessageSystemWillPowerOn ||
3795 messageType == kIOMessageSystemHasPoweredOn) {
3796 switch (messageType) {
3797 case kIOMessageSystemWillPowerOn:
3798 assert(lastSystemMessageType == kIOMessageSystemWillSleep);
3799 break;
3800 case kIOMessageSystemHasPoweredOn:
3801 assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3802 break;
3803 }
3804
3805 lastSystemMessageType = messageType;
3806 }
3807
3808 if (!gRootDomain) {
3809 return kIOReturnUnsupported;
3810 }
3811
3812 if (messageType == kIOMessageSystemCapabilityChange) {
3813 IOPMSystemCapabilityChangeParameters * params =
3814 (IOPMSystemCapabilityChangeParameters *) messageArgs;
3815
3816 // Interested applications have been notified of an impending power
3817 // change and have acked (when applicable).
3818 // This is our chance to save whatever state we can before powering
3819 // down.
3820 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3821 // via callout
3822
3823 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3824 params->fromCapabilities, params->toCapabilities,
3825 params->changeFlags);
3826
3827 if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3828 // We will ack within 20 seconds
3829 params->maxWaitForReply = 20 * 1000 * 1000;
3830
3831 #if HIBERNATION
3832 gRootDomain->evaluateSystemSleepPolicyEarly();
3833
3834 // add in time we could spend freeing pages
3835 if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3836 params->maxWaitForReply = kCapabilityClientMaxWait;
3837 }
3838 DLOG("sysPowerDownHandler max wait %d s\n",
3839 (int) (params->maxWaitForReply / 1000 / 1000));
3840 #endif
3841
3842 // Notify platform that sleep has begun, after the early
3843 // sleep policy evaluation.
3844 getPlatform()->callPlatformFunction(
3845 sleepMessagePEFunction.get(), false,
3846 (void *)(uintptr_t) kIOMessageSystemWillSleep,
3847 NULL, NULL, NULL);
3848
3849 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3850 // Purposely delay the ack and hope that shutdown occurs quickly.
3851 // Another option is not to schedule the thread and wait for
3852 // ack timeout...
3853 AbsoluteTime deadline;
3854 clock_interval_to_deadline( 30, kSecondScale, &deadline );
3855 thread_call_enter1_delayed(
3856 gRootDomain->diskSyncCalloutEntry,
3857 (thread_call_param_t)(uintptr_t) params->notifyRef,
3858 deadline );
3859 } else {
3860 thread_call_enter1(
3861 gRootDomain->diskSyncCalloutEntry,
3862 (thread_call_param_t)(uintptr_t) params->notifyRef);
3863 }
3864 }
3865 #if HIBERNATION
3866 else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
3867 // We will ack within 110 seconds
3868 params->maxWaitForReply = 110 * 1000 * 1000;
3869
3870 thread_call_enter1(
3871 gRootDomain->diskSyncCalloutEntry,
3872 (thread_call_param_t)(uintptr_t) params->notifyRef);
3873 }
3874 #endif
3875 ret = kIOReturnSuccess;
3876 }
3877
3878 return ret;
3879 }
3880
3881 //******************************************************************************
3882 // handleQueueSleepWakeUUID
3883 //
3884 // Called from IOPMrootDomain when we're initiating a sleep,
3885 // or indirectly from PM configd when PM decides to clear the UUID.
3886 // PM clears the UUID several minutes after successful wake from sleep,
3887 // so that we might associate App spindumps with the immediately previous
3888 // sleep/wake.
3889 //
3890 // @param obj has a retain on it. We're responsible for releasing that retain.
3891 //******************************************************************************
3892
3893 void
handleQueueSleepWakeUUID(OSObject * obj)3894 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
3895 {
3896 OSSharedPtr<OSString> str;
3897
3898 if (kOSBooleanFalse == obj) {
3899 handlePublishSleepWakeUUID(false);
3900 } else {
3901 str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
3902 if (str) {
3903 // This branch caches the UUID for an upcoming sleep/wake
3904 queuedSleepWakeUUIDString = str;
3905 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
3906 }
3907 }
3908 }
3909 //******************************************************************************
3910 // handlePublishSleepWakeUUID
3911 //
3912 // Called from IOPMrootDomain when we're initiating a sleep,
3913 // or indirectly from PM configd when PM decides to clear the UUID.
3914 // PM clears the UUID several minutes after successful wake from sleep,
3915 // so that we might associate App spindumps with the immediately previous
3916 // sleep/wake.
3917 //******************************************************************************
3918
3919 void
handlePublishSleepWakeUUID(bool shouldPublish)3920 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
3921 {
3922 ASSERT_GATED();
3923
3924 /*
3925 * Clear the current UUID
3926 */
3927 if (gSleepWakeUUIDIsSet) {
3928 DLOG("SleepWake UUID cleared\n");
3929
3930 gSleepWakeUUIDIsSet = false;
3931
3932 removeProperty(kIOPMSleepWakeUUIDKey);
3933 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
3934 }
3935
3936 /*
3937 * Optionally, publish a new UUID
3938 */
3939 if (queuedSleepWakeUUIDString && shouldPublish) {
3940 OSSharedPtr<OSString> publishThisUUID;
3941
3942 publishThisUUID = queuedSleepWakeUUIDString;
3943
3944 if (publishThisUUID) {
3945 setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
3946 }
3947
3948 gSleepWakeUUIDIsSet = true;
3949 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
3950
3951 queuedSleepWakeUUIDString.reset();
3952 }
3953 }
3954
3955 //******************************************************************************
3956 // IOPMGetSleepWakeUUIDKey
3957 //
3958 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3959 // To get the full key -- a C string -- the buffer must large enough for
3960 // the end-of-string character.
3961 // The key is expected to be an UUID string
3962 //******************************************************************************
3963
3964 extern "C" bool
IOPMCopySleepWakeUUIDKey(char * buffer,size_t buf_len)3965 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
3966 {
3967 if (!gSleepWakeUUIDIsSet) {
3968 return false;
3969 }
3970
3971 if (buffer != NULL) {
3972 OSSharedPtr<OSString> string =
3973 OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
3974
3975 if (!string) {
3976 *buffer = '\0';
3977 } else {
3978 strlcpy(buffer, string->getCStringNoCopy(), buf_len);
3979 }
3980 }
3981
3982 return true;
3983 }
3984
3985 //******************************************************************************
3986 // lowLatencyAudioNotify
3987 //
3988 // Used to send an update about low latency audio activity to interested
3989 // clients. To keep the overhead minimal the OSDictionary used here
3990 // is initialized at boot.
3991 //******************************************************************************
3992
3993 void
lowLatencyAudioNotify(uint64_t time,boolean_t state)3994 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
3995 {
3996 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
3997 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
3998 lowLatencyAudioNotifyTimestampVal->setValue(time);
3999 lowLatencyAudioNotifyStateVal->setValue(state);
4000 setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
4001 } else {
4002 DLOG("LowLatencyAudioNotify error\n");
4003 }
4004 return;
4005 }
4006
4007 //******************************************************************************
4008 // IOPMrootDomainRTNotifier
4009 //
4010 // Used by performance controller to update the timestamp and state associated
4011 // with low latency audio activity in the system.
4012 //******************************************************************************
4013
4014 extern "C" void
IOPMrootDomainRTNotifier(uint64_t time,boolean_t state)4015 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
4016 {
4017 gRootDomain->lowLatencyAudioNotify(time, state);
4018 return;
4019 }
4020
4021 //******************************************************************************
4022 // initializeBootSessionUUID
4023 //
4024 // Initialize the boot session uuid at boot up and sets it into registry.
4025 //******************************************************************************
4026
4027 void
initializeBootSessionUUID(void)4028 IOPMrootDomain::initializeBootSessionUUID(void)
4029 {
4030 uuid_t new_uuid;
4031 uuid_string_t new_uuid_string;
4032
4033 uuid_generate(new_uuid);
4034 uuid_unparse_upper(new_uuid, new_uuid_string);
4035 memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
4036
4037 setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
4038 }
4039
4040 //******************************************************************************
4041 // Root domain uses the private and tagged changePowerState methods for
4042 // tracking and logging purposes.
4043 //******************************************************************************
4044
4045 #define REQUEST_TAG_TO_REASON(x) ((uint16_t)x)
4046
4047 static uint32_t
nextRequestTag(IOPMRequestTag tag)4048 nextRequestTag( IOPMRequestTag tag )
4049 {
4050 static SInt16 msb16 = 1;
4051 uint16_t id = OSAddAtomic16(1, &msb16);
4052 return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
4053 }
4054
4055 // TODO: remove this shim function and exported symbol
4056 IOReturn
changePowerStateTo(unsigned long ordinal)4057 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
4058 {
4059 return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
4060 }
4061
4062 // TODO: remove this shim function and exported symbol
4063 IOReturn
changePowerStateToPriv(unsigned long ordinal)4064 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
4065 {
4066 return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
4067 }
4068
4069 IOReturn
changePowerStateWithOverrideTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4070 IOPMrootDomain::changePowerStateWithOverrideTo(
4071 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4072 {
4073 uint32_t tag = nextRequestTag(reason);
4074 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4075
4076 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4077 return kIOReturnUnsupported;
4078 }
4079
4080 return super::changePowerStateWithOverrideTo(ordinal, tag);
4081 }
4082
4083 IOReturn
changePowerStateWithTagTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4084 IOPMrootDomain::changePowerStateWithTagTo(
4085 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4086 {
4087 uint32_t tag = nextRequestTag(reason);
4088 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4089
4090 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4091 return kIOReturnUnsupported;
4092 }
4093
4094 return super::changePowerStateWithTagTo(ordinal, tag);
4095 }
4096
4097 IOReturn
changePowerStateWithTagToPriv(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4098 IOPMrootDomain::changePowerStateWithTagToPriv(
4099 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4100 {
4101 uint32_t tag = nextRequestTag(reason);
4102 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4103
4104 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4105 return kIOReturnUnsupported;
4106 }
4107
4108 return super::changePowerStateWithTagToPriv(ordinal, tag);
4109 }
4110
4111 //******************************************************************************
4112 // activity detect
4113 //
4114 //******************************************************************************
4115
4116 bool
activitySinceSleep(void)4117 IOPMrootDomain::activitySinceSleep(void)
4118 {
4119 return userActivityCount != userActivityAtSleep;
4120 }
4121
4122 bool
abortHibernation(void)4123 IOPMrootDomain::abortHibernation(void)
4124 {
4125 #if __arm64__
4126 // don't allow hibernation to be aborted on ARM due to user activity
4127 // since once ApplePMGR decides we're hibernating, we can't turn back
4128 // see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4129 return false;
4130 #else
4131 bool ret = activitySinceSleep();
4132
4133 if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4134 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4135 hibernateAborted = true;
4136 }
4137 return ret;
4138 #endif
4139 }
4140
4141 extern "C" int
hibernate_should_abort(void)4142 hibernate_should_abort(void)
4143 {
4144 if (gRootDomain) {
4145 return gRootDomain->abortHibernation();
4146 } else {
4147 return 0;
4148 }
4149 }
4150
4151 //******************************************************************************
4152 // willNotifyPowerChildren
4153 //
4154 // Called after all interested drivers have all acknowledged the power change,
4155 // but before any power children is informed. Dispatched though a thread call,
4156 // so it is safe to perform work that might block on a sleeping disk. PM state
4157 // machine (not thread) will block w/o timeout until this function returns.
4158 //******************************************************************************
4159
4160 void
willNotifyPowerChildren(IOPMPowerStateIndex newPowerState)4161 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4162 {
4163 OSSharedPtr<OSDictionary> dict;
4164 OSSharedPtr<OSNumber> secs;
4165
4166 if (SLEEP_STATE == newPowerState) {
4167 notifierThread = current_thread();
4168 if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
4169 AbsoluteTime deadline;
4170
4171 clock_interval_to_deadline(10, kSecondScale, &deadline);
4172 #if defined(XNU_TARGET_OS_OSX)
4173 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
4174 #endif /* defined(XNU_TARGET_OS_OSX) */
4175 }
4176
4177 _aotReadyToFullWake = false;
4178 #if 0
4179 if (_aotLingerTime) {
4180 uint64_t deadline;
4181 IOLog("aot linger no return\n");
4182 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
4183 clock_delay_until(deadline);
4184 }
4185 #endif
4186 if (!_aotMode) {
4187 _aotTestTime = 0;
4188 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4189 _aotLastWakeTime = 0;
4190 if (_aotMetrics) {
4191 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4192 }
4193 } else if (!_aotNow && !_debugWakeSeconds) {
4194 _aotNow = true;
4195 _aotPendingFlags = 0;
4196 _aotTasksSuspended = true;
4197 _aotLastWakeTime = 0;
4198 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4199 if (kIOPMAOTModeCycle & _aotMode) {
4200 clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
4201 _aotTestTime = mach_continuous_time() + _aotTestInterval;
4202 setWakeTime(_aotTestTime);
4203 }
4204 uint32_t lingerSecs;
4205 if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
4206 lingerSecs = 0;
4207 }
4208 clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
4209 clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
4210 clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
4211 }
4212
4213 #if HIBERNATION
4214 IOHibernateSystemSleep();
4215 IOHibernateIOKitSleep();
4216 #endif
4217 #if defined(__arm64__) && HIBERNATION
4218 // On AS, hibernation cannot be aborted. Resetting RTC to 1s during hibernation upon detecting
4219 // user activity is pointless (we are likely to spend >1s hibernating). It also clears existing
4220 // alarms, which can mess with cycler tools.
4221 if (gRootDomain->activitySinceSleep() && gIOHibernateState == kIOHibernateStateInactive) {
4222 #else /* defined(__arm64__) && HIBERNATION */
4223 // On non-AS, hibernation can be aborted if user activity is detected. So continue to reset the
4224 // RTC alarm (even during hibernation) so we can immediately wake from regular S2R if needed.
4225 if (gRootDomain->activitySinceSleep()) {
4226 #endif /* defined(__arm64__) && HIBERNATION */
4227 dict = OSDictionary::withCapacity(1);
4228 secs = OSNumber::withNumber(1, 32);
4229
4230 if (dict && secs) {
4231 dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4232 gRootDomain->setProperties(dict.get());
4233 MSG("Reverting sleep with relative wake\n");
4234 }
4235 }
4236
4237 notifierThread = NULL;
4238 }
4239 }
4240
4241 //******************************************************************************
4242 // willTellSystemCapabilityDidChange
4243 //
4244 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4245 // domain is raising its power state, immediately after notifying interested
4246 // drivers and power children.
4247 //******************************************************************************
4248
4249 void
4250 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4251 {
4252 if ((_systemTransitionType == kSystemTransitionWake) &&
4253 !CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
4254 // After powering up drivers, dark->full promotion on the current wake
4255 // transition is no longer possible. That is because the next machine
4256 // state will issue the system capability change messages.
4257 // The darkWakePowerClamped flag may already be set if the system has
4258 // at least one driver that was power clamped due to dark wake.
4259 // This function sets the darkWakePowerClamped flag in case there
4260 // is no power-clamped driver in the system.
4261 //
4262 // Last opportunity to exit dark wake using:
4263 // requestFullWake( kFullWakeReasonLocalUser );
4264
4265 if (!darkWakePowerClamped) {
4266 if (darkWakeLogClamp) {
4267 AbsoluteTime now;
4268 uint64_t nsec;
4269
4270 clock_get_uptime(&now);
4271 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
4272 absolutetime_to_nanoseconds(now, &nsec);
4273 DLOG("dark wake promotion disabled at %u ms\n",
4274 ((int)((nsec) / NSEC_PER_MSEC)));
4275 }
4276 darkWakePowerClamped = true;
4277 }
4278 }
4279 }
4280
4281 //******************************************************************************
4282 // sleepOnClamshellClosed
4283 //
4284 // contains the logic to determine if the system should sleep when the clamshell
4285 // is closed.
4286 //******************************************************************************
4287
4288 bool
4289 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4290 {
4291 if (!clamshellExists) {
4292 return false;
4293 }
4294
4295 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4296 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4297
4298 return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4299 }
4300
4301 bool
4302 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4303 {
4304 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4305 // closed && battery
4306 if (!clamshellExists) {
4307 return false;
4308 }
4309
4310 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4311 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4312
4313 return !acAdaptorConnected && !clamshellSleepDisableMask;
4314 }
4315
4316 void
4317 IOPMrootDomain::sendClientClamshellNotification( void )
4318 {
4319 /* Only broadcast clamshell alert if clamshell exists. */
4320 if (!clamshellExists) {
4321 return;
4322 }
4323
4324 setProperty(kAppleClamshellStateKey,
4325 clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4326
4327 setProperty(kAppleClamshellCausesSleepKey,
4328 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4329
4330 /* Argument to message is a bitfiel of
4331 * ( kClamshellStateBit | kClamshellSleepBit )
4332 */
4333 messageClients(kIOPMMessageClamshellStateChange,
4334 (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4335 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4336 }
4337
4338 //******************************************************************************
4339 // getSleepSupported
4340 //
4341 // Deprecated
4342 //******************************************************************************
4343
4344 IOOptionBits
4345 IOPMrootDomain::getSleepSupported( void )
4346 {
4347 return platformSleepSupport;
4348 }
4349
4350 //******************************************************************************
4351 // setSleepSupported
4352 //
4353 // Deprecated
4354 //******************************************************************************
4355
4356 void
4357 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4358 {
4359 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4360 OSBitOrAtomic(flags, &platformSleepSupport);
4361 }
4362
4363 //******************************************************************************
4364 // setClamShellSleepDisable
4365 //
4366 //******************************************************************************
4367
4368 void
4369 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4370 {
4371 uint32_t oldMask;
4372
4373 // User client calls this in non-gated context
4374 if (gIOPMWorkLoop->inGate() == false) {
4375 gIOPMWorkLoop->runAction(
4376 OSMemberFunctionCast(IOWorkLoop::Action, this,
4377 &IOPMrootDomain::setClamShellSleepDisable),
4378 (OSObject *) this,
4379 (void *) disable, (void *)(uintptr_t) bitmask);
4380 return;
4381 }
4382
4383 oldMask = clamshellSleepDisableMask;
4384 if (disable) {
4385 clamshellSleepDisableMask |= bitmask;
4386 } else {
4387 clamshellSleepDisableMask &= ~bitmask;
4388 }
4389 DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4390
4391 if (clamshellExists && clamshellClosed &&
4392 (clamshellSleepDisableMask != oldMask) &&
4393 (clamshellSleepDisableMask == 0)) {
4394 handlePowerNotification(kLocalEvalClamshellCommand);
4395 }
4396 }
4397
4398 //******************************************************************************
4399 // wakeFromDoze
4400 //
4401 // Deprecated.
4402 //******************************************************************************
4403
4404 void
4405 IOPMrootDomain::wakeFromDoze( void )
4406 {
4407 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4408 }
4409
4410 //******************************************************************************
4411 // recordRTCAlarm
4412 //
4413 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4414 // should be a dark wake or a full wake. Both Maintenance and SleepService
4415 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4416 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4417 // PMSettings are ignored.
4418 //
4419 // Caller serialized using settingsCtrlLock.
4420 //******************************************************************************
4421
4422 void
4423 IOPMrootDomain::recordRTCAlarm(
4424 const OSSymbol *type,
4425 OSObject *object )
4426 {
4427 uint32_t previousAlarmMask = _scheduledAlarmMask;
4428
4429 if (type == gIOPMSettingDebugWakeRelativeKey) {
4430 OSNumber * n = OSDynamicCast(OSNumber, object);
4431 if (n) {
4432 // Debug wake has highest scheduling priority so it overrides any
4433 // pre-existing alarm.
4434 uint32_t debugSecs = n->unsigned32BitValue();
4435 _nextScheduledAlarmType.reset(type, OSRetain);
4436 _nextScheduledAlarmUTC = debugSecs;
4437
4438 _debugWakeSeconds = debugSecs;
4439 OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4440 DLOG("next alarm (%s) in %u secs\n",
4441 type->getCStringNoCopy(), debugSecs);
4442 }
4443 } else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) ||
4444 (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) ||
4445 (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) {
4446 OSData * data = OSDynamicCast(OSData, object);
4447 if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) {
4448 const IOPMCalendarStruct * cs;
4449 bool replaceNextAlarm = false;
4450 clock_sec_t secs;
4451
4452 cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4453 secs = IOPMConvertCalendarToSeconds(cs);
4454 DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4455
4456 // Update the next scheduled alarm type
4457 if ((_nextScheduledAlarmType == NULL) ||
4458 ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4459 (secs < _nextScheduledAlarmUTC))) {
4460 replaceNextAlarm = true;
4461 }
4462
4463 if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4464 if (cs->year) {
4465 _calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4466 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4467 } else {
4468 // TODO: can this else-block be removed?
4469 _calendarWakeAlarmUTC = 0;
4470 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4471 }
4472 }
4473 if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4474 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4475 }
4476 if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4477 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4478 }
4479
4480 if (replaceNextAlarm) {
4481 _nextScheduledAlarmType.reset(type, OSRetain);
4482 _nextScheduledAlarmUTC = secs;
4483 DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4484 }
4485 }
4486 }
4487
4488 if (_scheduledAlarmMask != previousAlarmMask) {
4489 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4490 }
4491 }
4492
4493 // MARK: -
4494 // MARK: Features
4495
4496 //******************************************************************************
4497 // publishFeature
4498 //
4499 // Adds a new feature to the supported features dictionary
4500 //******************************************************************************
4501
4502 void
4503 IOPMrootDomain::publishFeature( const char * feature )
4504 {
4505 publishFeature(feature, kRD_AllPowerSources, NULL);
4506 }
4507
4508 //******************************************************************************
4509 // publishFeature (with supported power source specified)
4510 //
4511 // Adds a new feature to the supported features dictionary
4512 //******************************************************************************
4513
4514 void
4515 IOPMrootDomain::publishFeature(
4516 const char *feature,
4517 uint32_t supportedWhere,
4518 uint32_t *uniqueFeatureID)
4519 {
4520 static uint16_t next_feature_id = 500;
4521
4522 OSSharedPtr<OSNumber> new_feature_data;
4523 OSNumber *existing_feature = NULL;
4524 OSArray *existing_feature_arr_raw = NULL;
4525 OSSharedPtr<OSArray> existing_feature_arr;
4526 OSObject *osObj = NULL;
4527 uint32_t feature_value = 0;
4528
4529 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4530
4531 if (!supportedWhere) {
4532 // Feature isn't supported anywhere!
4533 return;
4534 }
4535
4536 if (next_feature_id > 5000) {
4537 // Far, far too many features!
4538 return;
4539 }
4540
4541 if (featuresDictLock) {
4542 IOLockLock(featuresDictLock);
4543 }
4544
4545 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4546 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4547 OSSharedPtr<OSDictionary> features;
4548
4549 // Create new features dict if necessary
4550 if (origFeatures) {
4551 features = OSDictionary::withDictionary(origFeatures);
4552 } else {
4553 features = OSDictionary::withCapacity(1);
4554 }
4555
4556 // Create OSNumber to track new feature
4557
4558 next_feature_id += 1;
4559 if (uniqueFeatureID) {
4560 // We don't really mind if the calling kext didn't give us a place
4561 // to stash their unique id. Many kexts don't plan to unload, and thus
4562 // have no need to remove themselves later.
4563 *uniqueFeatureID = next_feature_id;
4564 }
4565
4566 feature_value = (uint32_t)next_feature_id;
4567 feature_value <<= 16;
4568 feature_value += supportedWhere;
4569
4570 new_feature_data = OSNumber::withNumber(
4571 (unsigned long long)feature_value, 32);
4572
4573 // Does features object already exist?
4574 if ((osObj = features->getObject(feature))) {
4575 if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
4576 // We need to create an OSArray to hold the now 2 elements.
4577 existing_feature_arr = OSArray::withObjects(
4578 (const OSObject **)&existing_feature, 1, 2);
4579 } else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) {
4580 // Add object to existing array
4581 existing_feature_arr = OSArray::withArray(
4582 existing_feature_arr_raw,
4583 existing_feature_arr_raw->getCount() + 1);
4584 }
4585
4586 if (existing_feature_arr) {
4587 existing_feature_arr->setObject(new_feature_data.get());
4588 features->setObject(feature, existing_feature_arr.get());
4589 }
4590 } else {
4591 // The easy case: no previously existing features listed. We simply
4592 // set the OSNumber at key 'feature' and we're on our way.
4593 features->setObject(feature, new_feature_data.get());
4594 }
4595
4596 setProperty(kRootDomainSupportedFeatures, features.get());
4597
4598 if (featuresDictLock) {
4599 IOLockUnlock(featuresDictLock);
4600 }
4601
4602 // Notify EnergySaver and all those in user space so they might
4603 // re-populate their feature specific UI
4604 if (pmPowerStateQueue) {
4605 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4606 }
4607 }
4608
4609 //******************************************************************************
4610 // removePublishedFeature
4611 //
4612 // Removes previously published feature
4613 //******************************************************************************
4614
4615 IOReturn
4616 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4617 {
4618 IOReturn ret = kIOReturnError;
4619 uint32_t feature_value = 0;
4620 uint16_t feature_id = 0;
4621 bool madeAChange = false;
4622
4623 OSSymbol *dictKey = NULL;
4624 OSSharedPtr<OSCollectionIterator> dictIterator;
4625 OSArray *arrayMember = NULL;
4626 OSNumber *numberMember = NULL;
4627 OSObject *osObj = NULL;
4628 OSNumber *osNum = NULL;
4629 OSSharedPtr<OSArray> arrayMemberCopy;
4630
4631 if (kBadPMFeatureID == removeFeatureID) {
4632 return kIOReturnNotFound;
4633 }
4634
4635 if (featuresDictLock) {
4636 IOLockLock(featuresDictLock);
4637 }
4638
4639 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4640 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4641 OSSharedPtr<OSDictionary> features;
4642
4643 if (origFeatures) {
4644 // Any modifications to the dictionary are made to the copy to prevent
4645 // races & crashes with userland clients. Dictionary updated
4646 // automically later.
4647 features = OSDictionary::withDictionary(origFeatures);
4648 } else {
4649 features = NULL;
4650 ret = kIOReturnNotFound;
4651 goto exit;
4652 }
4653
4654 // We iterate 'features' dictionary looking for an entry tagged
4655 // with 'removeFeatureID'. If found, we remove it from our tracking
4656 // structures and notify the OS via a general interest message.
4657
4658 dictIterator = OSCollectionIterator::withCollection(features.get());
4659 if (!dictIterator) {
4660 goto exit;
4661 }
4662
4663 while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4664 osObj = features->getObject(dictKey);
4665
4666 // Each Feature is either tracked by an OSNumber
4667 if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
4668 feature_value = numberMember->unsigned32BitValue();
4669 feature_id = (uint16_t)(feature_value >> 16);
4670
4671 if (feature_id == (uint16_t)removeFeatureID) {
4672 // Remove this node
4673 features->removeObject(dictKey);
4674 madeAChange = true;
4675 break;
4676 }
4677
4678 // Or tracked by an OSArray of OSNumbers
4679 } else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4680 unsigned int arrayCount = arrayMember->getCount();
4681
4682 for (unsigned int i = 0; i < arrayCount; i++) {
4683 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4684 if (!osNum) {
4685 continue;
4686 }
4687
4688 feature_value = osNum->unsigned32BitValue();
4689 feature_id = (uint16_t)(feature_value >> 16);
4690
4691 if (feature_id == (uint16_t)removeFeatureID) {
4692 // Remove this node
4693 if (1 == arrayCount) {
4694 // If the array only contains one element, remove
4695 // the whole thing.
4696 features->removeObject(dictKey);
4697 } else {
4698 // Otherwise remove the element from a copy of the array.
4699 arrayMemberCopy = OSArray::withArray(arrayMember);
4700 if (arrayMemberCopy) {
4701 arrayMemberCopy->removeObject(i);
4702 features->setObject(dictKey, arrayMemberCopy.get());
4703 }
4704 }
4705
4706 madeAChange = true;
4707 break;
4708 }
4709 }
4710 }
4711 }
4712
4713 if (madeAChange) {
4714 ret = kIOReturnSuccess;
4715
4716 setProperty(kRootDomainSupportedFeatures, features.get());
4717
4718 // Notify EnergySaver and all those in user space so they might
4719 // re-populate their feature specific UI
4720 if (pmPowerStateQueue) {
4721 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4722 }
4723 } else {
4724 ret = kIOReturnNotFound;
4725 }
4726
4727 exit:
4728 if (featuresDictLock) {
4729 IOLockUnlock(featuresDictLock);
4730 }
4731 return ret;
4732 }
4733
4734 //******************************************************************************
4735 // publishPMSetting (private)
4736 //
4737 // Should only be called by PMSettingObject to publish a PM Setting as a
4738 // supported feature.
4739 //******************************************************************************
4740
4741 void
4742 IOPMrootDomain::publishPMSetting(
4743 const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4744 {
4745 if (noPublishPMSettings &&
4746 (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4747 // Setting found in noPublishPMSettings array
4748 *featureID = kBadPMFeatureID;
4749 return;
4750 }
4751
4752 publishFeature(
4753 feature->getCStringNoCopy(), where, featureID);
4754 }
4755
4756 //******************************************************************************
4757 // setPMSetting (private)
4758 //
4759 // Internal helper to relay PM settings changes from user space to individual
4760 // drivers. Should be called only by IOPMrootDomain::setProperties.
4761 //******************************************************************************
4762
4763 IOReturn
4764 IOPMrootDomain::setPMSetting(
4765 const OSSymbol *type,
4766 OSObject *object )
4767 {
4768 PMSettingCallEntry *entries = NULL;
4769 OSSharedPtr<OSArray> chosen;
4770 const OSArray *array;
4771 PMSettingObject *pmso;
4772 thread_t thisThread;
4773 int i, j, count, capacity;
4774 bool ok = false;
4775 IOReturn ret;
4776
4777 if (NULL == type) {
4778 return kIOReturnBadArgument;
4779 }
4780
4781 PMSETTING_LOCK();
4782
4783 // Update settings dict so changes are visible from copyPMSetting().
4784 fPMSettingsDict->setObject(type, object);
4785
4786 // Prep all PMSetting objects with the given 'type' for callout.
4787 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
4788 if (!array || ((capacity = array->getCount()) == 0)) {
4789 goto unlock_exit;
4790 }
4791
4792 // Array to retain PMSetting objects targeted for callout.
4793 chosen = OSArray::withCapacity(capacity);
4794 if (!chosen) {
4795 goto unlock_exit; // error
4796 }
4797 entries = IONew(PMSettingCallEntry, capacity);
4798 if (!entries) {
4799 goto unlock_exit; // error
4800 }
4801 memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4802
4803 thisThread = current_thread();
4804
4805 for (i = 0, j = 0; i < capacity; i++) {
4806 pmso = (PMSettingObject *) array->getObject(i);
4807 if (pmso->disabled) {
4808 continue;
4809 }
4810 entries[j].thread = thisThread;
4811 queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4812 chosen->setObject(pmso);
4813 j++;
4814 }
4815 count = j;
4816 if (!count) {
4817 goto unlock_exit;
4818 }
4819
4820 PMSETTING_UNLOCK();
4821
4822 // Call each pmso in the chosen array.
4823 for (i = 0; i < count; i++) {
4824 pmso = (PMSettingObject *) chosen->getObject(i);
4825 ret = pmso->dispatchPMSetting(type, object);
4826 if (ret == kIOReturnSuccess) {
4827 // At least one setting handler was successful
4828 ok = true;
4829 #if DEVELOPMENT || DEBUG
4830 } else {
4831 // Log the handler and kext that failed
4832 OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
4833 if (kextName) {
4834 DLOG("PMSetting(%s) error 0x%x from %s\n",
4835 type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
4836 }
4837 #endif
4838 }
4839 }
4840
4841 PMSETTING_LOCK();
4842 for (i = 0; i < count; i++) {
4843 pmso = (PMSettingObject *) chosen->getObject(i);
4844 queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
4845 if (pmso->waitThread) {
4846 PMSETTING_WAKEUP(pmso);
4847 }
4848 }
4849
4850 if (ok) {
4851 recordRTCAlarm(type, object);
4852 }
4853 unlock_exit:
4854 PMSETTING_UNLOCK();
4855
4856 if (entries) {
4857 IODelete(entries, PMSettingCallEntry, capacity);
4858 }
4859
4860 return kIOReturnSuccess;
4861 }
4862
4863 //******************************************************************************
4864 // copyPMSetting (public)
4865 //
4866 // Allows kexts to safely read setting values, without being subscribed to
4867 // notifications.
4868 //******************************************************************************
4869
4870 OSSharedPtr<OSObject>
4871 IOPMrootDomain::copyPMSetting(
4872 OSSymbol *whichSetting)
4873 {
4874 OSSharedPtr<OSObject> obj;
4875
4876 if (!whichSetting) {
4877 return NULL;
4878 }
4879
4880 PMSETTING_LOCK();
4881 obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
4882 PMSETTING_UNLOCK();
4883
4884 return obj;
4885 }
4886
4887 //******************************************************************************
4888 // registerPMSettingController (public)
4889 //
4890 // direct wrapper to registerPMSettingController with uint32_t power source arg
4891 //******************************************************************************
4892
4893 IOReturn
4894 IOPMrootDomain::registerPMSettingController(
4895 const OSSymbol * settings[],
4896 IOPMSettingControllerCallback func,
4897 OSObject *target,
4898 uintptr_t refcon,
4899 OSObject **handle)
4900 {
4901 return registerPMSettingController(
4902 settings,
4903 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
4904 func, target, refcon, handle);
4905 }
4906
4907 //******************************************************************************
4908 // registerPMSettingController (public)
4909 //
4910 // Kexts may register for notifications when a particular setting is changed.
4911 // A list of settings is available in IOPM.h.
4912 // Arguments:
4913 // * settings - An OSArray containing OSSymbols. Caller should populate this
4914 // array with a list of settings caller wants notifications from.
4915 // * func - A C function callback of the type IOPMSettingControllerCallback
4916 // * target - caller may provide an OSObject *, which PM will pass as an
4917 // target to calls to "func"
4918 // * refcon - caller may provide an void *, which PM will pass as an
4919 // argument to calls to "func"
4920 // * handle - This is a return argument. We will populate this pointer upon
4921 // call success. Hold onto this and pass this argument to
4922 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4923 // Returns:
4924 // kIOReturnSuccess on success
4925 //******************************************************************************
4926
4927 IOReturn
4928 IOPMrootDomain::registerPMSettingController(
4929 const OSSymbol * settings[],
4930 uint32_t supportedPowerSources,
4931 IOPMSettingControllerCallback func,
4932 OSObject *target,
4933 uintptr_t refcon,
4934 OSObject **handle)
4935 {
4936 PMSettingObject *pmso = NULL;
4937 OSObject *pmsh = NULL;
4938 int i;
4939
4940 if (NULL == settings ||
4941 NULL == func ||
4942 NULL == handle) {
4943 return kIOReturnBadArgument;
4944 }
4945
4946 pmso = PMSettingObject::pmSettingObject(
4947 (IOPMrootDomain *) this, func, target,
4948 refcon, supportedPowerSources, settings, &pmsh);
4949
4950 if (!pmso) {
4951 *handle = NULL;
4952 return kIOReturnInternalError;
4953 }
4954
4955 PMSETTING_LOCK();
4956 for (i = 0; settings[i]; i++) {
4957 OSSharedPtr<OSArray> newList;
4958 OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
4959 if (!list) {
4960 // New array of callbacks for this setting
4961 newList = OSArray::withCapacity(1);
4962 settingsCallbacks->setObject(settings[i], newList.get());
4963 list = newList.get();
4964 }
4965
4966 // Add caller to the callback list
4967 list->setObject(pmso);
4968 }
4969 PMSETTING_UNLOCK();
4970
4971 // Return handle to the caller, the setting object is private.
4972 *handle = pmsh;
4973
4974 return kIOReturnSuccess;
4975 }
4976
4977 //******************************************************************************
4978 // deregisterPMSettingObject (private)
4979 //
4980 // Only called from PMSettingObject.
4981 //******************************************************************************
4982
4983 void
4984 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
4985 {
4986 thread_t thisThread = current_thread();
4987 PMSettingCallEntry *callEntry;
4988 OSSharedPtr<OSCollectionIterator> iter;
4989 OSSymbol *sym;
4990 OSArray *array;
4991 int index;
4992 bool wait;
4993
4994 PMSETTING_LOCK();
4995
4996 pmso->disabled = true;
4997
4998 // Wait for all callout threads to finish.
4999 do {
5000 wait = false;
5001 queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
5002 {
5003 if (callEntry->thread != thisThread) {
5004 wait = true;
5005 break;
5006 }
5007 }
5008 if (wait) {
5009 assert(NULL == pmso->waitThread);
5010 pmso->waitThread = thisThread;
5011 PMSETTING_WAIT(pmso);
5012 pmso->waitThread = NULL;
5013 }
5014 } while (wait);
5015
5016 // Search each PM settings array in the kernel.
5017 iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
5018 if (iter) {
5019 while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
5020 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
5021 index = array->getNextIndexOfObject(pmso, 0);
5022 if (-1 != index) {
5023 array->removeObject(index);
5024 }
5025 }
5026 }
5027
5028 PMSETTING_UNLOCK();
5029
5030 pmso->release();
5031 }
5032
5033 //******************************************************************************
5034 // informCPUStateChange
5035 //
5036 // Call into PM CPU code so that CPU power savings may dynamically adjust for
5037 // running on battery, with the lid closed, etc.
5038 //
5039 // informCPUStateChange is a no-op on non x86 systems
5040 // only x86 has explicit support in the IntelCPUPowerManagement kext
5041 //******************************************************************************
5042
5043 void
5044 IOPMrootDomain::informCPUStateChange(
5045 uint32_t type,
5046 uint32_t value )
5047 {
5048 #if defined(__i386__) || defined(__x86_64__)
5049
5050 pmioctlVariableInfo_t varInfoStruct;
5051 int pmCPUret = 0;
5052 const char *varNameStr = NULL;
5053 int32_t *varIndex = NULL;
5054
5055 if (kInformAC == type) {
5056 varNameStr = kIOPMRootDomainBatPowerCString;
5057 varIndex = &idxPMCPULimitedPower;
5058 } else if (kInformLid == type) {
5059 varNameStr = kIOPMRootDomainLidCloseCString;
5060 varIndex = &idxPMCPUClamshell;
5061 } else {
5062 return;
5063 }
5064
5065 // Set the new value!
5066 // pmCPUControl will assign us a new ID if one doesn't exist yet
5067 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
5068 varInfoStruct.varID = *varIndex;
5069 varInfoStruct.varType = vBool;
5070 varInfoStruct.varInitValue = value;
5071 varInfoStruct.varCurValue = value;
5072 strlcpy((char *)varInfoStruct.varName,
5073 (const char *)varNameStr,
5074 sizeof(varInfoStruct.varName));
5075
5076 // Set!
5077 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
5078
5079 // pmCPU only assigns numerical id's when a new varName is specified
5080 if ((0 == pmCPUret)
5081 && (*varIndex == kCPUUnknownIndex)) {
5082 // pmCPUControl has assigned us a new variable ID.
5083 // Let's re-read the structure we just SET to learn that ID.
5084 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
5085
5086 if (0 == pmCPUret) {
5087 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5088 *varIndex = varInfoStruct.varID;
5089 }
5090 }
5091
5092 return;
5093
5094 #endif /* __i386__ || __x86_64__ */
5095 }
5096
5097 // MARK: -
5098 // MARK: Deep Sleep Policy
5099
5100 #if HIBERNATION
5101
5102 //******************************************************************************
5103 // evaluateSystemSleepPolicy
5104 //******************************************************************************
5105
5106 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
5107
5108 // Sleep flags
5109 enum {
5110 kIOPMSleepFlagHibernate = 0x00000001,
5111 kIOPMSleepFlagSleepTimerEnable = 0x00000002
5112 };
5113
5114 struct IOPMSystemSleepPolicyEntry {
5115 uint32_t factorMask;
5116 uint32_t factorBits;
5117 uint32_t sleepFlags;
5118 uint32_t wakeEvents;
5119 } __attribute__((packed));
5120
5121 struct IOPMSystemSleepPolicyTable {
5122 uint32_t signature;
5123 uint16_t version;
5124 uint16_t entryCount;
5125 IOPMSystemSleepPolicyEntry entries[];
5126 } __attribute__((packed));
5127
5128 enum {
5129 kIOPMSleepAttributeHibernateSetup = 0x00000001,
5130 kIOPMSleepAttributeHibernateSleep = 0x00000002
5131 };
5132
5133 static uint32_t
5134 getSleepTypeAttributes( uint32_t sleepType )
5135 {
5136 static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5137 {
5138 /* invalid */ 0,
5139 /* abort */ 0,
5140 /* normal */ 0,
5141 /* safesleep */ kIOPMSleepAttributeHibernateSetup,
5142 /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5143 /* standby */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5144 /* poweroff */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5145 /* deepidle */ 0
5146 };
5147
5148 if (sleepType >= kIOPMSleepTypeLast) {
5149 return 0;
5150 }
5151
5152 return sleepTypeAttributes[sleepType];
5153 }
5154
5155 bool
5156 IOPMrootDomain::evaluateSystemSleepPolicy(
5157 IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5158 {
5159 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5160
5161 static const IONamedValue factorValues[] = {
5162 SLEEP_FACTOR( SleepTimerWake ),
5163 SLEEP_FACTOR( LidOpen ),
5164 SLEEP_FACTOR( ACPower ),
5165 SLEEP_FACTOR( BatteryLow ),
5166 SLEEP_FACTOR( StandbyNoDelay ),
5167 SLEEP_FACTOR( StandbyForced ),
5168 SLEEP_FACTOR( StandbyDisabled ),
5169 SLEEP_FACTOR( USBExternalDevice ),
5170 SLEEP_FACTOR( BluetoothHIDDevice ),
5171 SLEEP_FACTOR( ExternalMediaMounted ),
5172 SLEEP_FACTOR( ThunderboltDevice ),
5173 SLEEP_FACTOR( RTCAlarmScheduled ),
5174 SLEEP_FACTOR( MagicPacketWakeEnabled ),
5175 SLEEP_FACTOR( HibernateForced ),
5176 SLEEP_FACTOR( AutoPowerOffDisabled ),
5177 SLEEP_FACTOR( AutoPowerOffForced ),
5178 SLEEP_FACTOR( ExternalDisplay ),
5179 SLEEP_FACTOR( NetworkKeepAliveActive ),
5180 SLEEP_FACTOR( LocalUserActivity ),
5181 SLEEP_FACTOR( HibernateFailed ),
5182 SLEEP_FACTOR( ThermalWarning ),
5183 SLEEP_FACTOR( DisplayCaptured ),
5184 { 0, NULL }
5185 };
5186
5187 const IOPMSystemSleepPolicyTable * pt;
5188 OSSharedPtr<OSObject> prop;
5189 OSData * policyData;
5190 uint64_t currentFactors = 0;
5191 char currentFactorsBuf[512];
5192 uint32_t standbyDelay = 0;
5193 uint32_t powerOffDelay = 0;
5194 uint32_t powerOffTimer = 0;
5195 uint32_t standbyTimer = 0;
5196 uint32_t mismatch;
5197 bool standbyEnabled;
5198 bool powerOffEnabled;
5199 bool found = false;
5200
5201 // Get platform's sleep policy table
5202 if (!gSleepPolicyHandler) {
5203 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5204 if (!prop) {
5205 goto done;
5206 }
5207 }
5208
5209 // Fetch additional settings
5210 standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
5211 && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue));
5212 powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
5213 && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue));
5214 if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
5215 powerOffTimer = powerOffDelay;
5216 }
5217 if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5218 standbyTimer = standbyDelay;
5219 }
5220
5221 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5222 sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
5223 powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
5224
5225 currentFactorsBuf[0] = 0;
5226 // pmset level overrides
5227 if ((*hibMode & kIOHibernateModeOn) == 0) {
5228 if (!gSleepPolicyHandler) {
5229 standbyEnabled = false;
5230 powerOffEnabled = false;
5231 }
5232 } else if (!(*hibMode & kIOHibernateModeSleep)) {
5233 // Force hibernate (i.e. mode 25)
5234 // If standby is enabled, force standy.
5235 // If poweroff is enabled, force poweroff.
5236 if (standbyEnabled) {
5237 currentFactors |= kIOPMSleepFactorStandbyForced;
5238 } else if (powerOffEnabled) {
5239 currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
5240 } else {
5241 currentFactors |= kIOPMSleepFactorHibernateForced;
5242 }
5243 }
5244
5245 // Current factors based on environment and assertions
5246 if (sleepTimerMaintenance) {
5247 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5248 }
5249 if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5250 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5251 }
5252 if (!clamshellClosed) {
5253 currentFactors |= kIOPMSleepFactorLidOpen;
5254 }
5255 if (acAdaptorConnected) {
5256 currentFactors |= kIOPMSleepFactorACPower;
5257 }
5258 if (lowBatteryCondition) {
5259 hibernateMode = 0;
5260 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5261 if ((hibernateMode & kIOHibernateModeOn) == 0) {
5262 DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5263 } else {
5264 currentFactors |= kIOPMSleepFactorBatteryLow;
5265 }
5266 }
5267 if (!standbyDelay || !standbyTimer) {
5268 currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5269 }
5270 if (standbyNixed || !standbyEnabled) {
5271 currentFactors |= kIOPMSleepFactorStandbyDisabled;
5272 }
5273 if (resetTimers) {
5274 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5275 currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5276 }
5277 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5278 kIOPMDriverAssertionLevelOff) {
5279 currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5280 }
5281 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5282 kIOPMDriverAssertionLevelOff) {
5283 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5284 }
5285 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5286 kIOPMDriverAssertionLevelOff) {
5287 currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5288 }
5289 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5290 kIOPMDriverAssertionLevelOff) {
5291 currentFactors |= kIOPMSleepFactorThunderboltDevice;
5292 }
5293 if (_scheduledAlarmMask != 0) {
5294 currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5295 }
5296 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5297 kIOPMDriverAssertionLevelOff) {
5298 currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5299 }
5300 #define TCPKEEPALIVE 1
5301 #if TCPKEEPALIVE
5302 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5303 kIOPMDriverAssertionLevelOff) {
5304 currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5305 }
5306 #endif
5307 if (!powerOffEnabled) {
5308 currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5309 }
5310 if (desktopMode) {
5311 currentFactors |= kIOPMSleepFactorExternalDisplay;
5312 }
5313 if (userWasActive) {
5314 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5315 }
5316 if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5317 currentFactors |= kIOPMSleepFactorHibernateFailed;
5318 }
5319 if (thermalWarningState) {
5320 currentFactors |= kIOPMSleepFactorThermalWarning;
5321 }
5322
5323 for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) {
5324 uint32_t factor = 1 << factorBit;
5325 if (factor & currentFactors) {
5326 strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf));
5327 strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf));
5328 }
5329 }
5330 DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5331
5332 if (gSleepPolicyHandler) {
5333 uint32_t savedHibernateMode;
5334 IOReturn result;
5335
5336 if (!gSleepPolicyVars) {
5337 gSleepPolicyVars = IOMallocType(IOPMSystemSleepPolicyVariables);
5338 }
5339 gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
5340 gSleepPolicyVars->version = kIOPMSystemSleepPolicyVersion;
5341 gSleepPolicyVars->currentCapability = _currentCapability;
5342 gSleepPolicyVars->highestCapability = _highestCapability;
5343 gSleepPolicyVars->sleepFactors = currentFactors;
5344 gSleepPolicyVars->sleepReason = lastSleepReason;
5345 gSleepPolicyVars->sleepPhase = sleepPhase;
5346 gSleepPolicyVars->standbyDelay = standbyDelay;
5347 gSleepPolicyVars->standbyTimer = standbyTimer;
5348 gSleepPolicyVars->poweroffDelay = powerOffDelay;
5349 gSleepPolicyVars->scheduledAlarms = _scheduledAlarmMask | _userScheduledAlarmMask;
5350 gSleepPolicyVars->poweroffTimer = powerOffTimer;
5351
5352 if (kIOPMSleepPhase0 == sleepPhase) {
5353 // preserve hibernateMode
5354 savedHibernateMode = gSleepPolicyVars->hibernateMode;
5355 gSleepPolicyVars->hibernateMode = *hibMode;
5356 } else if (kIOPMSleepPhase1 == sleepPhase) {
5357 // use original hibernateMode for phase2
5358 gSleepPolicyVars->hibernateMode = *hibMode;
5359 }
5360
5361 result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5362
5363 if (kIOPMSleepPhase0 == sleepPhase) {
5364 // restore hibernateMode
5365 gSleepPolicyVars->hibernateMode = savedHibernateMode;
5366 }
5367
5368 if ((result != kIOReturnSuccess) ||
5369 (kIOPMSleepTypeInvalid == params->sleepType) ||
5370 (params->sleepType >= kIOPMSleepTypeLast) ||
5371 (kIOPMSystemSleepParametersVersion != params->version)) {
5372 MSG("sleep policy handler error\n");
5373 goto done;
5374 }
5375
5376 if ((getSleepTypeAttributes(params->sleepType) &
5377 kIOPMSleepAttributeHibernateSetup) &&
5378 ((*hibMode & kIOHibernateModeOn) == 0)) {
5379 *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5380 }
5381
5382 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5383 params->version, params->sleepType, params->sleepFlags,
5384 params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
5385 found = true;
5386 goto done;
5387 }
5388
5389 // Policy table is meaningless without standby enabled
5390 if (!standbyEnabled) {
5391 goto done;
5392 }
5393
5394 // Validate the sleep policy table
5395 policyData = OSDynamicCast(OSData, prop.get());
5396 if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5397 goto done;
5398 }
5399
5400 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5401 if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5402 (pt->version != 1) || (0 == pt->entryCount)) {
5403 goto done;
5404 }
5405
5406 if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5407 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5408 goto done;
5409 }
5410
5411 for (uint32_t i = 0; i < pt->entryCount; i++) {
5412 const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
5413 mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
5414
5415 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5416 entry->factorMask, entry->factorBits,
5417 entry->sleepFlags, entry->wakeEvents, mismatch);
5418 if (mismatch) {
5419 continue;
5420 }
5421
5422 DLOG("^ found match\n");
5423 found = true;
5424
5425 params->version = kIOPMSystemSleepParametersVersion;
5426 params->reserved1 = 1;
5427 if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5428 params->sleepType = kIOPMSleepTypeStandby;
5429 } else {
5430 params->sleepType = kIOPMSleepTypeNormalSleep;
5431 }
5432
5433 params->ecWakeEvents = entry->wakeEvents;
5434 if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5435 if (kIOPMSleepPhase2 == sleepPhase) {
5436 clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5437
5438 if (!_standbyTimerResetSeconds ||
5439 (now_secs <= _standbyTimerResetSeconds)) {
5440 // Reset standby timer adjustment
5441 _standbyTimerResetSeconds = now_secs;
5442 DLOG("standby delay %u, reset %u\n",
5443 standbyDelay, (uint32_t) _standbyTimerResetSeconds);
5444 } else if (standbyDelay) {
5445 // Shorten the standby delay timer
5446 clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
5447 if (standbyDelay > elapsed) {
5448 standbyDelay -= elapsed;
5449 } else {
5450 standbyDelay = 1; // must be > 0
5451 }
5452 DLOG("standby delay %u, elapsed %u\n",
5453 standbyDelay, (uint32_t) elapsed);
5454 }
5455 }
5456 params->ecWakeTimer = standbyDelay;
5457 } else if (kIOPMSleepPhase2 == sleepPhase) {
5458 // A sleep that does not enable the sleep timer will reset
5459 // the standby delay adjustment.
5460 _standbyTimerResetSeconds = 0;
5461 }
5462 break;
5463 }
5464
5465 done:
5466 return found;
5467 }
5468
5469 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5470
5471 void
5472 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5473 {
5474 // Evaluate early (priority interest phase), before drivers sleep.
5475
5476 DLOG("%s\n", __FUNCTION__);
5477 removeProperty(kIOPMSystemSleepParametersKey);
5478
5479 // Full wake resets the standby timer delay adjustment
5480 if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5481 _standbyTimerResetSeconds = 0;
5482 }
5483
5484 hibernateDisabled = false;
5485 hibernateMode = 0;
5486 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5487
5488 // Save for late evaluation if sleep is aborted
5489 bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5490
5491 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5492 &hibernateMode)) {
5493 if (!hibernateRetry &&
5494 ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5495 kIOPMSleepAttributeHibernateSetup) == 0)) {
5496 // skip hibernate setup
5497 hibernateDisabled = true;
5498 }
5499 }
5500
5501 // Publish IOPMSystemSleepType
5502 uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5503 if (sleepType == kIOPMSleepTypeInvalid) {
5504 // no sleep policy
5505 sleepType = kIOPMSleepTypeNormalSleep;
5506 if (hibernateMode & kIOHibernateModeOn) {
5507 sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5508 kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5509 }
5510 } else if ((sleepType == kIOPMSleepTypeStandby) &&
5511 (gEarlySystemSleepParams.ecPoweroffTimer)) {
5512 // report the lowest possible sleep state
5513 sleepType = kIOPMSleepTypePowerOff;
5514 }
5515
5516 setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5517 }
5518
5519 void
5520 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5521 {
5522 IOPMSystemSleepParameters params;
5523 OSSharedPtr<OSData> paramsData;
5524 bool wakeNow;
5525 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5526
5527 DLOG("%s\n", __FUNCTION__);
5528
5529 bzero(¶ms, sizeof(params));
5530 wakeNow = false;
5531 if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2, &hibernateMode)) {
5532 if ((kIOPMSleepTypeStandby == params.sleepType)
5533 && gIOHibernateStandbyDisabled && gSleepPolicyVars
5534 && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5535 & gSleepPolicyVars->sleepFactors))) {
5536 standbyNixed = true;
5537 wakeNow = true;
5538 }
5539 if (wakeNow
5540 || ((hibernateDisabled || hibernateAborted) &&
5541 (getSleepTypeAttributes(params.sleepType) &
5542 kIOPMSleepAttributeHibernateSetup))) {
5543 // Final evaluation picked a state requiring hibernation,
5544 // but hibernate isn't going to proceed. Arm a short sleep using
5545 // the early non-hibernate sleep parameters.
5546 bcopy(&gEarlySystemSleepParams, ¶ms, sizeof(params));
5547 params.sleepType = kIOPMSleepTypeAbortedSleep;
5548 params.ecWakeTimer = 1;
5549 if (standbyNixed) {
5550 resetTimers = true;
5551 } else {
5552 // Set hibernateRetry flag to force hibernate setup on the
5553 // next sleep.
5554 hibernateRetry = true;
5555 }
5556 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5557 params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5558 } else {
5559 hibernateRetry = false;
5560 }
5561
5562 if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5563 resetTimers = false;
5564 }
5565
5566 paramsData = OSData::withValue(params);
5567 if (paramsData) {
5568 setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5569 }
5570
5571 if (getSleepTypeAttributes(params.sleepType) &
5572 kIOPMSleepAttributeHibernateSleep) {
5573 // Disable sleep to force hibernation
5574 gIOHibernateMode &= ~kIOHibernateModeSleep;
5575 }
5576 }
5577 }
5578
5579 bool
5580 IOPMrootDomain::getHibernateSettings(
5581 uint32_t * hibernateModePtr,
5582 uint32_t * hibernateFreeRatio,
5583 uint32_t * hibernateFreeTime )
5584 {
5585 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5586 // has updated the hibernateDisabled flag.
5587
5588 bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
5589 getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
5590 getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
5591 if (hibernateDisabled) {
5592 *hibernateModePtr = 0;
5593 } else if (gSleepPolicyHandler) {
5594 *hibernateModePtr = hibernateMode;
5595 }
5596 DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5597 return ok;
5598 }
5599
5600 bool
5601 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5602 {
5603 OSSharedPtr<OSObject> optionsProp;
5604 OSDictionary * optionsDict;
5605 OSSharedPtr<OSObject> obj;
5606 OSNumber * num;
5607 bool ok = false;
5608
5609 optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5610 optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5611
5612 if (optionsDict) {
5613 obj.reset(optionsDict->getObject(key), OSRetain);
5614 }
5615 if (!obj) {
5616 obj = copyProperty(key);
5617 }
5618 if (obj) {
5619 if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5620 *option = num->unsigned32BitValue();
5621 ok = true;
5622 } else if (OSDynamicCast(OSBoolean, obj.get())) {
5623 *option = (obj == kOSBooleanTrue) ? 1 : 0;
5624 ok = true;
5625 }
5626 }
5627
5628 return ok;
5629 }
5630 #endif /* HIBERNATION */
5631
5632 IOReturn
5633 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5634 {
5635 #if HIBERNATION
5636 IOPMSystemSleepParameters params;
5637 uint32_t hibMode = 0;
5638 bool ok;
5639
5640 if (gIOPMWorkLoop->inGate() == false) {
5641 IOReturn ret = gIOPMWorkLoop->runAction(
5642 OSMemberFunctionCast(IOWorkLoop::Action, this,
5643 &IOPMrootDomain::getSystemSleepType),
5644 (OSObject *) this,
5645 (void *) sleepType, (void *) standbyTimer);
5646 return ret;
5647 }
5648
5649 getSleepOption(kIOHibernateModeKey, &hibMode);
5650 bzero(¶ms, sizeof(params));
5651
5652 ok = evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase0, &hibMode);
5653 if (ok) {
5654 *sleepType = params.sleepType;
5655 if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5656 !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5657 DLOG("Standby delay is not set\n");
5658 *standbyTimer = 0;
5659 }
5660 return kIOReturnSuccess;
5661 }
5662 #endif
5663
5664 return kIOReturnUnsupported;
5665 }
5666
5667 // MARK: -
5668 // MARK: Shutdown and Restart
5669
5670 //******************************************************************************
5671 // handlePlatformHaltRestart
5672 //
5673 //******************************************************************************
5674
5675 // Phases while performing shutdown/restart
5676 typedef enum {
5677 kNotifyDone = 0x00,
5678 kNotifyPriorityClients = 0x10,
5679 kNotifyPowerPlaneDrivers = 0x20,
5680 kNotifyHaltRestartAction = 0x30,
5681 kQuiescePM = 0x40,
5682 } shutdownPhase_t;
5683
5684
5685 struct HaltRestartApplierContext {
5686 IOPMrootDomain * RootDomain;
5687 unsigned long PowerState;
5688 IOPMPowerFlags PowerFlags;
5689 UInt32 MessageType;
5690 UInt32 Counter;
5691 const char * LogString;
5692 shutdownPhase_t phase;
5693
5694 IOServiceInterestHandler handler;
5695 } gHaltRestartCtx;
5696
5697 const char *
5698 shutdownPhase2String(shutdownPhase_t phase)
5699 {
5700 switch (phase) {
5701 case kNotifyDone:
5702 return "Notifications completed";
5703 case kNotifyPriorityClients:
5704 return "Notifying priority clients";
5705 case kNotifyPowerPlaneDrivers:
5706 return "Notifying power plane drivers";
5707 case kNotifyHaltRestartAction:
5708 return "Notifying HaltRestart action handlers";
5709 case kQuiescePM:
5710 return "Quiescing PM";
5711 default:
5712 return "Unknown";
5713 }
5714 }
5715
5716 static void
5717 platformHaltRestartApplier( OSObject * object, void * context )
5718 {
5719 IOPowerStateChangeNotification notify;
5720 HaltRestartApplierContext * ctx;
5721 AbsoluteTime startTime, elapsedTime;
5722 uint32_t deltaTime;
5723
5724 ctx = (HaltRestartApplierContext *) context;
5725
5726 _IOServiceInterestNotifier * notifier;
5727 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5728 memset(¬ify, 0, sizeof(notify));
5729 notify.powerRef = (void *)(uintptr_t)ctx->Counter;
5730 notify.returnValue = 0;
5731 notify.stateNumber = ctx->PowerState;
5732 notify.stateFlags = ctx->PowerFlags;
5733
5734 if (notifier) {
5735 ctx->handler = notifier->handler;
5736 }
5737
5738 clock_get_uptime(&startTime);
5739 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)¬ify );
5740 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5741
5742 if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
5743 LOG("%s handler %p took %u ms\n",
5744 ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
5745 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
5746 }
5747
5748 ctx->handler = NULL;
5749 ctx->Counter++;
5750 }
5751
5752 static void
5753 quiescePowerTreeCallback( void * target, void * param )
5754 {
5755 IOLockLock(gPMHaltLock);
5756 gPMQuiesced = true;
5757 thread_wakeup(param);
5758 IOLockUnlock(gPMHaltLock);
5759 }
5760
5761 void
5762 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5763 {
5764 AbsoluteTime startTime, elapsedTime;
5765 uint32_t deltaTime;
5766 bool nvramSync = false;
5767
5768 memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5769 gHaltRestartCtx.RootDomain = this;
5770
5771 clock_get_uptime(&startTime);
5772 switch (pe_type) {
5773 case kPEHaltCPU:
5774 case kPEUPSDelayHaltCPU:
5775 gHaltRestartCtx.PowerState = OFF_STATE;
5776 gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5777 gHaltRestartCtx.LogString = "PowerOff";
5778 nvramSync = true;
5779 break;
5780
5781 case kPERestartCPU:
5782 gHaltRestartCtx.PowerState = RESTART_STATE;
5783 gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5784 gHaltRestartCtx.LogString = "Restart";
5785 nvramSync = true;
5786 break;
5787
5788 case kPEPagingOff:
5789 gHaltRestartCtx.PowerState = ON_STATE;
5790 gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5791 gHaltRestartCtx.LogString = "PagingOff";
5792 IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5793 #if HIBERNATION
5794 IOHibernateSystemRestart();
5795 #endif
5796 break;
5797
5798 default:
5799 return;
5800 }
5801
5802 if (nvramSync) {
5803 PESyncNVRAM();
5804 }
5805
5806 gHaltRestartCtx.phase = kNotifyPriorityClients;
5807 // Notify legacy clients
5808 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5809
5810 // For normal shutdown, turn off File Server Mode.
5811 if (kPEHaltCPU == pe_type) {
5812 OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
5813 OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32);
5814 if (setting && num) {
5815 setPMSetting(setting.get(), num.get());
5816 }
5817 }
5818
5819 if (kPEPagingOff != pe_type) {
5820 gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5821 // Notify in power tree order
5822 notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5823 }
5824
5825 gHaltRestartCtx.phase = kNotifyHaltRestartAction;
5826 #if defined(XNU_TARGET_OS_OSX)
5827 IOCPURunPlatformHaltRestartActions(pe_type);
5828 #else /* !defined(XNU_TARGET_OS_OSX) */
5829 if (kPEPagingOff != pe_type) {
5830 IOCPURunPlatformHaltRestartActions(pe_type);
5831 }
5832 #endif /* !defined(XNU_TARGET_OS_OSX) */
5833
5834 // Wait for PM to quiesce
5835 if ((kPEPagingOff != pe_type) && gPMHaltLock) {
5836 gHaltRestartCtx.phase = kQuiescePM;
5837 AbsoluteTime quiesceTime = mach_absolute_time();
5838
5839 IOLockLock(gPMHaltLock);
5840 gPMQuiesced = false;
5841 if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
5842 kIOReturnSuccess) {
5843 while (!gPMQuiesced) {
5844 IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
5845 }
5846 }
5847 IOLockUnlock(gPMHaltLock);
5848 deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
5849 DLOG("PM quiesce took %u ms\n", deltaTime);
5850 halt_log_enter("Quiesce", NULL, elapsedTime);
5851 }
5852 gHaltRestartCtx.phase = kNotifyDone;
5853
5854 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5855 LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5856
5857 halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
5858
5859 deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5860 LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5861
5862 if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
5863 printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
5864 }
5865
5866 checkShutdownTimeout();
5867 }
5868
5869 bool
5870 IOPMrootDomain::checkShutdownTimeout()
5871 {
5872 AbsoluteTime elapsedTime;
5873 uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5874
5875 if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
5876 return true;
5877 }
5878 return false;
5879 }
5880
5881 void
5882 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
5883 {
5884 if (gHaltLog) {
5885 if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
5886 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
5887 }
5888 panic("%s timed out in phase '%s'. Total %d ms:%s",
5889 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
5890 } else {
5891 panic("%s timed out in phase \'%s\'. Total %d ms",
5892 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
5893 }
5894 }
5895
5896 //******************************************************************************
5897 // shutdownSystem
5898 //
5899 //******************************************************************************
5900
5901 IOReturn
5902 IOPMrootDomain::shutdownSystem( void )
5903 {
5904 return kIOReturnUnsupported;
5905 }
5906
5907 //******************************************************************************
5908 // restartSystem
5909 //
5910 //******************************************************************************
5911
5912 IOReturn
5913 IOPMrootDomain::restartSystem( void )
5914 {
5915 return kIOReturnUnsupported;
5916 }
5917
5918 // MARK: -
5919 // MARK: System Capability
5920
5921 //******************************************************************************
5922 // tagPowerPlaneService
5923 //
5924 // Running on PM work loop thread.
5925 //******************************************************************************
5926
5927 void
5928 IOPMrootDomain::tagPowerPlaneService(
5929 IOService * service,
5930 IOPMActions * actions,
5931 IOPMPowerStateIndex maxPowerState )
5932 {
5933 uint32_t flags = 0;
5934
5935 memset(actions, 0, sizeof(*actions));
5936 actions->target = this;
5937
5938 if (service == this) {
5939 actions->actionPowerChangeStart =
5940 OSMemberFunctionCast(
5941 IOPMActionPowerChangeStart, this,
5942 &IOPMrootDomain::handleOurPowerChangeStart);
5943
5944 actions->actionPowerChangeDone =
5945 OSMemberFunctionCast(
5946 IOPMActionPowerChangeDone, this,
5947 &IOPMrootDomain::handleOurPowerChangeDone);
5948
5949 actions->actionPowerChangeOverride =
5950 OSMemberFunctionCast(
5951 IOPMActionPowerChangeOverride, this,
5952 &IOPMrootDomain::overrideOurPowerChange);
5953 return;
5954 }
5955
5956 #if DISPLAY_WRANGLER_PRESENT
5957 if (NULL != service->metaCast("IODisplayWrangler")) {
5958 // XXX should this really retain?
5959 wrangler.reset(service, OSRetain);
5960 wrangler->registerInterest(gIOGeneralInterest,
5961 &displayWranglerNotification, this, NULL);
5962
5963 // found the display wrangler, check for any display assertions already created
5964 if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
5965 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5966 wrangler->setIgnoreIdleTimer( true );
5967 }
5968 flags |= kPMActionsFlagIsDisplayWrangler;
5969 }
5970 #endif /* DISPLAY_WRANGLER_PRESENT */
5971
5972 if (service->propertyExists("IOPMStrictTreeOrder")) {
5973 flags |= kPMActionsFlagIsGraphicsDriver;
5974 }
5975 if (service->propertyExists("IOPMUnattendedWakePowerState")) {
5976 flags |= kPMActionsFlagIsAudioDriver;
5977 }
5978
5979 // Find the power connection object that is a child of the PCI host
5980 // bridge, and has a graphics/audio device attached below. Mark the
5981 // power branch for delayed child notifications.
5982
5983 if (flags) {
5984 IORegistryEntry * child = service;
5985 IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
5986
5987 while (child != this) {
5988 if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) {
5989 // Skip delaying notifications and clamping power on external graphics and audio devices.
5990 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
5991 flags = 0;
5992 break;
5993 }
5994 if ((parent == pciHostBridgeDriver) ||
5995 (parent == this)) {
5996 if (OSDynamicCast(IOPowerConnection, child)) {
5997 IOPowerConnection * conn = (IOPowerConnection *) child;
5998 conn->delayChildNotification = true;
5999 DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
6000 }
6001 break;
6002 }
6003 child = parent;
6004 parent = child->getParentEntry(gIOPowerPlane);
6005 }
6006 }
6007
6008 OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
6009 if (prop) {
6010 OSNumber * num = OSDynamicCast(OSNumber, prop.get());
6011 if (num) {
6012 actions->darkWakePowerState = num->unsigned32BitValue();
6013 if (actions->darkWakePowerState < maxPowerState) {
6014 flags |= kPMActionsFlagHasDarkWakePowerState;
6015 }
6016 }
6017 }
6018
6019
6020 if (flags) {
6021 DLOG("%s tag flags %x\n", service->getName(), flags);
6022 actions->flags |= flags;
6023 actions->actionPowerChangeOverride =
6024 OSMemberFunctionCast(
6025 IOPMActionPowerChangeOverride, this,
6026 &IOPMrootDomain::overridePowerChangeForService);
6027
6028 if (flags & kPMActionsFlagIsDisplayWrangler) {
6029 actions->actionActivityTickle =
6030 OSMemberFunctionCast(
6031 IOPMActionActivityTickle, this,
6032 &IOPMrootDomain::handleActivityTickleForDisplayWrangler);
6033
6034 actions->actionUpdatePowerClient =
6035 OSMemberFunctionCast(
6036 IOPMActionUpdatePowerClient, this,
6037 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
6038 }
6039 return;
6040 }
6041
6042 // Locate the first PCI host bridge for PMTrace.
6043 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
6044 IOService * provider = service->getProvider();
6045 if (OSDynamicCast(IOPlatformDevice, provider) &&
6046 provider->inPlane(gIODTPlane)) {
6047 pciHostBridgeDevice.reset(provider, OSNoRetain);
6048 pciHostBridgeDriver.reset(service, OSNoRetain);
6049 DLOG("PMTrace found PCI host bridge %s->%s\n",
6050 provider->getName(), service->getName());
6051 }
6052 }
6053
6054 // Tag top-level PCI devices. The order of PMinit() call does not
6055 // change across boots and is used as the PCI bit number.
6056 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
6057 // Would prefer to check built-in property, but tagPowerPlaneService()
6058 // is called before pciDevice->registerService().
6059 IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
6060 if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) {
6061 int bit = pmTracer->recordTopLevelPCIDevice( service );
6062 if (bit >= 0) {
6063 // Save the assigned bit for fast lookup.
6064 actions->flags |= (bit & kPMActionsPCIBitNumberMask);
6065
6066 actions->actionPowerChangeStart =
6067 OSMemberFunctionCast(
6068 IOPMActionPowerChangeStart, this,
6069 &IOPMrootDomain::handlePowerChangeStartForPCIDevice);
6070
6071 actions->actionPowerChangeDone =
6072 OSMemberFunctionCast(
6073 IOPMActionPowerChangeDone, this,
6074 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
6075 }
6076 }
6077 }
6078 }
6079
6080 //******************************************************************************
6081 // PM actions for root domain
6082 //******************************************************************************
6083
6084 void
6085 IOPMrootDomain::overrideOurPowerChange(
6086 IOService * service,
6087 IOPMActions * actions,
6088 const IOPMRequest * request,
6089 IOPMPowerStateIndex * inOutPowerState,
6090 IOPMPowerChangeFlags * inOutChangeFlags )
6091 {
6092 uint32_t changeFlags = *inOutChangeFlags;
6093 uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
6094 uint32_t currentPowerState = (uint32_t) getPowerState();
6095
6096 if (request->getTag() == 0) {
6097 // Set a tag for any request that originates from IOServicePM
6098 (const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
6099 }
6100
6101 DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6102 getPowerStateString(currentPowerState),
6103 getPowerStateString(desiredPowerState),
6104 _currentCapability, changeFlags,
6105 request->getTag());
6106
6107
6108 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6109 /*
6110 * ASBM send lowBattery notifications every 1 second until the device
6111 * enters hibernation. This queues up multiple sleep requests.
6112 * After the device wakes from hibernation, none of these previously
6113 * queued sleep requests are valid.
6114 * lowBattteryCondition variable is set when ASBM notifies rootDomain
6115 * and is cleared at the very last point in sleep.
6116 * Any attempt to sleep with reason kIOPMSleepReasonLowPower without
6117 * lowBatteryCondition is invalid
6118 */
6119 if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) {
6120 if (!lowBatteryCondition) {
6121 DLOG("Duplicate lowBattery sleep");
6122 *inOutChangeFlags |= kIOPMNotDone;
6123 return;
6124 }
6125 }
6126 #endif
6127
6128 if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
6129 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6130 *inOutChangeFlags |= kIOPMNotDone;
6131 return;
6132 }
6133
6134 if (changeFlags & kIOPMParentInitiated) {
6135 // Root parent is permanently pegged at max power,
6136 // a parent initiated power change is unexpected.
6137 *inOutChangeFlags |= kIOPMNotDone;
6138 return;
6139 }
6140
6141 if (desiredPowerState < currentPowerState) {
6142 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6143 // Root domain is dropping power state from ON->SLEEP.
6144 // If system is in full wake, first enter dark wake by
6145 // converting the power drop to a capability change.
6146 // Once in dark wake, transition to sleep state ASAP.
6147
6148 darkWakeToSleepASAP = true;
6149
6150 // Drop graphics and audio capability
6151 _desiredCapability &= ~(
6152 kIOPMSystemCapabilityGraphics |
6153 kIOPMSystemCapabilityAudio);
6154
6155 // Convert to capability change (ON->ON)
6156 *inOutPowerState = getRUN_STATE();
6157 *inOutChangeFlags |= kIOPMSynchronize;
6158
6159 // Revert device desire from SLEEP to ON
6160 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6161 } else {
6162 // System is already in dark wake, ok to drop power state.
6163 // Broadcast root power down to entire tree.
6164 *inOutChangeFlags |= kIOPMRootChangeDown;
6165 }
6166 } else if (desiredPowerState > currentPowerState) {
6167 if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
6168 // Broadcast power up when waking from sleep, but not for the
6169 // initial power change at boot by checking for cpu capability.
6170 *inOutChangeFlags |= kIOPMRootChangeUp;
6171 }
6172 }
6173 }
6174
6175 void
6176 IOPMrootDomain::handleOurPowerChangeStart(
6177 IOService * service,
6178 IOPMActions * actions,
6179 const IOPMRequest * request,
6180 IOPMPowerStateIndex newPowerState,
6181 IOPMPowerChangeFlags * inOutChangeFlags )
6182 {
6183 IOPMRequestTag requestTag = request->getTag();
6184 IOPMRequestTag sleepReason;
6185
6186 uint32_t changeFlags = *inOutChangeFlags;
6187 uint32_t currentPowerState = (uint32_t) getPowerState();
6188 bool publishSleepReason = false;
6189
6190 // Check if request has a valid sleep reason
6191 sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6192 if (sleepReason < kIOPMSleepReasonClamshell) {
6193 sleepReason = kIOPMSleepReasonIdle;
6194 }
6195
6196 _systemTransitionType = kSystemTransitionNone;
6197 _systemMessageClientMask = 0;
6198 capabilityLoss = false;
6199 toldPowerdCapWillChange = false;
6200
6201 // Emergency notifications may arrive after the initial sleep request
6202 // has been queued. Override the sleep reason so powerd and others can
6203 // treat this as an emergency sleep.
6204 if (lowBatteryCondition) {
6205 sleepReason = kIOPMSleepReasonLowPower;
6206 } else if (thermalEmergencyState) {
6207 sleepReason = kIOPMSleepReasonThermalEmergency;
6208 }
6209
6210 // 1. Explicit capability change.
6211 if (changeFlags & kIOPMSynchronize) {
6212 if (newPowerState == ON_STATE) {
6213 if (changeFlags & kIOPMSyncNoChildNotify) {
6214 _systemTransitionType = kSystemTransitionNewCapClient;
6215 } else {
6216 _systemTransitionType = kSystemTransitionCapability;
6217 }
6218 }
6219 }
6220 // 2. Going to sleep (cancellation still possible).
6221 else if (newPowerState < currentPowerState) {
6222 _systemTransitionType = kSystemTransitionSleep;
6223 }
6224 // 3. Woke from (idle or demand) sleep.
6225 else if (!systemBooting &&
6226 (changeFlags & kIOPMSelfInitiated) &&
6227 (newPowerState > currentPowerState)) {
6228 _systemTransitionType = kSystemTransitionWake;
6229 _desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
6230
6231 // Early exit from dark wake to full (e.g. LID open)
6232 if (kFullWakeReasonNone != fullWakeReason) {
6233 _desiredCapability |= (
6234 kIOPMSystemCapabilityGraphics |
6235 kIOPMSystemCapabilityAudio);
6236
6237 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6238 if (fullWakeReason == kFullWakeReasonLocalUser) {
6239 darkWakeExit = true;
6240 darkWakeToSleepASAP = false;
6241 setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ?
6242 kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser);
6243 }
6244 #endif
6245 }
6246 #if HIBERNATION
6247 IOHibernateSetWakeCapabilities(_desiredCapability);
6248 #endif
6249 }
6250
6251 // Update pending wake capability at the beginning of every
6252 // state transition (including synchronize). This will become
6253 // the current capability at the end of the transition.
6254
6255 if (kSystemTransitionSleep == _systemTransitionType) {
6256 _pendingCapability = 0;
6257 capabilityLoss = true;
6258 } else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6259 _pendingCapability = _desiredCapability |
6260 kIOPMSystemCapabilityCPU |
6261 kIOPMSystemCapabilityNetwork;
6262
6263 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6264 _pendingCapability |= kIOPMSystemCapabilityAudio;
6265 }
6266
6267 if ((kSystemTransitionCapability == _systemTransitionType) &&
6268 (_pendingCapability == _currentCapability)) {
6269 // Cancel the PM state change.
6270 _systemTransitionType = kSystemTransitionNone;
6271 *inOutChangeFlags |= kIOPMNotDone;
6272 }
6273 if (__builtin_popcount(_pendingCapability) <
6274 __builtin_popcount(_currentCapability)) {
6275 capabilityLoss = true;
6276 }
6277 }
6278
6279 // 1. Capability change.
6280 if (kSystemTransitionCapability == _systemTransitionType) {
6281 // Dark to Full transition.
6282 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6283 tracePoint( kIOPMTracePointDarkWakeExit );
6284
6285 #if defined(XNU_TARGET_OS_OSX)
6286 // rdar://problem/65627936
6287 // When a dark->full wake promotion is scheduled before an ON->SLEEP
6288 // power state drop, invalidate any request to drop power state already
6289 // in the queue, including the override variant, unless full wake cannot
6290 // be sustained. Any power state drop queued after this SustainFullWake
6291 // request will not be affected.
6292 if (checkSystemCanSustainFullWake()) {
6293 changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake);
6294 }
6295 #endif
6296
6297 willEnterFullWake();
6298 }
6299
6300 // Full to Dark transition.
6301 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6302 // Clear previous stats
6303 IOLockLock(pmStatsLock);
6304 if (pmStatsAppResponses) {
6305 pmStatsAppResponses = OSArray::withCapacity(5);
6306 }
6307 IOLockUnlock(pmStatsLock);
6308
6309 tracePoint( kIOPMTracePointDarkWakeEntry );
6310 *inOutChangeFlags |= kIOPMSyncTellPowerDown;
6311 _systemMessageClientMask = kSystemMessageClientPowerd |
6312 kSystemMessageClientLegacyApp;
6313
6314 // rdar://15971327
6315 // Prevent user active transitions before notifying clients
6316 // that system will sleep.
6317 preventTransitionToUserActive(true);
6318
6319 IOService::setAdvisoryTickleEnable( false );
6320
6321 // Publish the sleep reason for full to dark wake
6322 publishSleepReason = true;
6323 lastSleepReason = fullToDarkReason = sleepReason;
6324
6325 // Publish a UUID for the Sleep --> Wake cycle
6326 handlePublishSleepWakeUUID(true);
6327 if (sleepDelaysReport) {
6328 clock_get_uptime(&ts_sleepStart);
6329 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
6330 }
6331
6332 darkWakeExit = false;
6333 }
6334 }
6335 // 2. System sleep.
6336 else if (kSystemTransitionSleep == _systemTransitionType) {
6337 // Beginning of a system sleep transition.
6338 // Cancellation is still possible.
6339 tracePoint( kIOPMTracePointSleepStarted );
6340
6341 _systemMessageClientMask = kSystemMessageClientAll;
6342 if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6343 _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6344 }
6345 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
6346 // Kernel priority clients are only notified on the initial
6347 // transition to full wake, so don't notify them unless system
6348 // has gained graphics capability since the last system wake.
6349 _systemMessageClientMask &= ~kSystemMessageClientKernel;
6350 } else {
6351 // System was in full wake, but the downwards power transition is driven
6352 // by a request that originates from IOServicePM, so it isn't tagged with
6353 // a valid system sleep reason.
6354 if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) {
6355 // Publish the same reason for full to dark
6356 sleepReason = fullToDarkReason;
6357 }
6358 }
6359 #if HIBERNATION
6360 gIOHibernateState = 0;
6361 #endif
6362
6363 // Record the reason for dark wake back to sleep
6364 // System may not have ever achieved full wake
6365
6366 publishSleepReason = true;
6367 lastSleepReason = sleepReason;
6368 if (sleepDelaysReport) {
6369 clock_get_uptime(&ts_sleepStart);
6370 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
6371 }
6372 }
6373 // 3. System wake.
6374 else if (kSystemTransitionWake == _systemTransitionType) {
6375 tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6376 // Clear stats about sleep
6377
6378 if (AOT_STATE == newPowerState) {
6379 _pendingCapability = 0;
6380 }
6381
6382 if (AOT_STATE == currentPowerState) {
6383 // Wake events are no longer accepted after waking to AOT_STATE.
6384 // Re-enable wake event acceptance to append wake events claimed
6385 // during the AOT to ON_STATE transition.
6386 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable);
6387 }
6388
6389 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6390 willEnterFullWake();
6391 }
6392 }
6393
6394 // The only location where the sleep reason is published. At this point
6395 // sleep can still be cancelled, but sleep reason should be published
6396 // early for logging purposes.
6397
6398 if (publishSleepReason) {
6399 static const char * IOPMSleepReasons[] =
6400 {
6401 kIOPMClamshellSleepKey,
6402 kIOPMPowerButtonSleepKey,
6403 kIOPMSoftwareSleepKey,
6404 kIOPMOSSwitchHibernationKey,
6405 kIOPMIdleSleepKey,
6406 kIOPMLowPowerSleepKey,
6407 kIOPMThermalEmergencySleepKey,
6408 kIOPMMaintenanceSleepKey,
6409 kIOPMSleepServiceExitKey,
6410 kIOPMDarkWakeThermalEmergencyKey,
6411 kIOPMNotificationWakeExitKey
6412 };
6413
6414 // Record sleep cause in IORegistry
6415 uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
6416 if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
6417 DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
6418 #if DEVELOPMENT || DEBUG
6419 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6420 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6421 "Sleep Reason", "%s\n", IOPMSleepReasons[reasonIndex]
6422 );
6423 #endif /* DEVELOPMENT || DEBUG */
6424 setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
6425 }
6426 }
6427
6428 if ((kSystemTransitionNone != _systemTransitionType) &&
6429 (kSystemTransitionNewCapClient != _systemTransitionType)) {
6430 _systemStateGeneration++;
6431 systemDarkWake = false;
6432
6433 DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6434 getPowerStateString(currentPowerState),
6435 getPowerStateString((uint32_t) newPowerState),
6436 _currentCapability, _pendingCapability,
6437 *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask,
6438 requestTag);
6439 #if DEVELOPMENT || DEBUG
6440 if (currentPowerState != (uint32_t) newPowerState) {
6441 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6442 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6443 "Start Power State Trans.",
6444 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6445 getPowerStateString(currentPowerState),
6446 getPowerStateString((uint32_t) newPowerState),
6447 _currentCapability,
6448 _pendingCapability,
6449 *inOutChangeFlags,
6450 _systemStateGeneration,
6451 _systemMessageClientMask,
6452 requestTag
6453 );
6454 }
6455 #endif /* DEVELOPMENT || DEBUG */
6456 }
6457
6458 if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6459 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6460 }
6461 if (_aotNow && (ON_STATE == newPowerState)) {
6462 WAKEEVENT_LOCK();
6463 aotShouldExit(false, true);
6464 WAKEEVENT_UNLOCK();
6465 aotExit(false);
6466 }
6467 }
6468
6469 void
6470 IOPMrootDomain::handleOurPowerChangeDone(
6471 IOService * service,
6472 IOPMActions * actions,
6473 const IOPMRequest * request,
6474 IOPMPowerStateIndex oldPowerState,
6475 IOPMPowerChangeFlags changeFlags )
6476 {
6477 if (kSystemTransitionNewCapClient == _systemTransitionType) {
6478 _systemTransitionType = kSystemTransitionNone;
6479 return;
6480 }
6481
6482 if (_systemTransitionType != kSystemTransitionNone) {
6483 uint32_t currentPowerState = (uint32_t) getPowerState();
6484
6485 if (changeFlags & kIOPMNotDone) {
6486 // Power down was cancelled or vetoed.
6487 _pendingCapability = _currentCapability;
6488 lastSleepReason = 0;
6489
6490 // When sleep is cancelled or reverted, don't report
6491 // the target (lower) power state as the previous state.
6492 oldPowerState = currentPowerState;
6493
6494 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
6495 CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
6496 #if defined(XNU_TARGET_OS_OSX)
6497 pmPowerStateQueue->submitPowerEvent(
6498 kPowerEventPolicyStimulus,
6499 (void *) kStimulusDarkWakeReentry,
6500 _systemStateGeneration );
6501 #else /* !defined(XNU_TARGET_OS_OSX) */
6502 // On embedded, there are no factors that can prolong a
6503 // "darkWake" when a power down is vetoed. We need to
6504 // promote to "fullWake" at least once so that factors
6505 // that prevent idle sleep can assert themselves if required
6506 pmPowerStateQueue->submitPowerEvent(
6507 kPowerEventPolicyStimulus,
6508 (void *) kStimulusDarkWakeActivityTickle);
6509 #endif /* !defined(XNU_TARGET_OS_OSX) */
6510 }
6511
6512 // Revert device desire to max.
6513 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6514 } else {
6515 // Send message on dark wake to full wake promotion.
6516 // tellChangeUp() handles the normal SLEEP->ON case.
6517
6518 if (kSystemTransitionCapability == _systemTransitionType) {
6519 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6520 lastSleepReason = 0; // stop logging wrangler tickles
6521 tellClients(kIOMessageSystemHasPoweredOn);
6522 }
6523 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6524 // Going dark, reset full wake state
6525 // userIsActive will be cleared by wrangler powering down
6526 fullWakeReason = kFullWakeReasonNone;
6527
6528 if (ts_sleepStart) {
6529 clock_get_uptime(&wake2DarkwakeDelay);
6530 SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
6531 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
6532 ts_sleepStart = 0;
6533 }
6534 }
6535 }
6536
6537 // Reset state after exiting from dark wake.
6538
6539 if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6540 CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6541 darkWakeMaintenance = false;
6542 darkWakeToSleepASAP = false;
6543 pciCantSleepValid = false;
6544 darkWakeSleepService = false;
6545
6546 if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6547 // Remove the influence of display power assertion
6548 // before next system wake.
6549 if (wrangler) {
6550 wrangler->changePowerStateForRootDomain(
6551 kWranglerPowerStateMin );
6552 }
6553 removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6554 }
6555 }
6556
6557 // Entered dark mode.
6558
6559 if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6560 (_pendingCapability & kIOPMSystemCapabilityCPU)) {
6561 // Queue an evaluation of whether to remain in dark wake,
6562 // and for how long. This serves the purpose of draining
6563 // any assertions from the queue.
6564
6565 pmPowerStateQueue->submitPowerEvent(
6566 kPowerEventPolicyStimulus,
6567 (void *) kStimulusDarkWakeEntry,
6568 _systemStateGeneration );
6569 }
6570 }
6571
6572 #if DEVELOPMENT || DEBUG
6573 if (currentPowerState != (uint32_t) oldPowerState) {
6574 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6575 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6576 "Finish Power State Trans.",
6577 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6578 getPowerStateString((uint32_t)oldPowerState),
6579 getPowerStateString(currentPowerState),
6580 _currentCapability,
6581 _pendingCapability,
6582 changeFlags,
6583 _systemStateGeneration,
6584 _systemMessageClientMask,
6585 request->getTag()
6586 );
6587 }
6588 #endif /* DEVELOPMENT || DEBUG */
6589
6590 DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6591 getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState),
6592 _currentCapability, _pendingCapability,
6593 changeFlags, _systemStateGeneration, _systemMessageClientMask,
6594 request->getTag());
6595
6596 if ((currentPowerState == ON_STATE) && pmAssertions) {
6597 pmAssertions->reportCPUBitAccounting();
6598 }
6599
6600 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6601 displayWakeCnt++;
6602 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6603 if (clamshellExists && fullWakeThreadCall) {
6604 AbsoluteTime deadline;
6605 clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline);
6606 thread_call_enter_delayed(fullWakeThreadCall, deadline);
6607 }
6608 #endif
6609 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6610 darkWakeCnt++;
6611 }
6612
6613 // Update current system capability.
6614 if (_currentCapability != _pendingCapability) {
6615 _currentCapability = _pendingCapability;
6616 }
6617
6618 // Update highest system capability.
6619
6620 _highestCapability |= _currentCapability;
6621
6622 if (darkWakePostTickle &&
6623 (kSystemTransitionWake == _systemTransitionType) &&
6624 (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6625 kDarkWakeFlagPromotionLate) {
6626 darkWakePostTickle = false;
6627 reportUserInput();
6628 } else if (darkWakeExit) {
6629 requestFullWake( kFullWakeReasonLocalUser );
6630 }
6631
6632 // Reset tracepoint at completion of capability change,
6633 // completion of wake transition, and aborted sleep transition.
6634
6635 if ((_systemTransitionType == kSystemTransitionCapability) ||
6636 (_systemTransitionType == kSystemTransitionWake) ||
6637 ((_systemTransitionType == kSystemTransitionSleep) &&
6638 (changeFlags & kIOPMNotDone))) {
6639 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6640 tracePoint( kIOPMTracePointSystemUp );
6641 }
6642
6643 _systemTransitionType = kSystemTransitionNone;
6644 _systemMessageClientMask = 0;
6645 toldPowerdCapWillChange = false;
6646
6647 darkWakeLogClamp = false;
6648
6649 if (lowBatteryCondition) {
6650 privateSleepSystem(kIOPMSleepReasonLowPower);
6651 } else if (thermalEmergencyState) {
6652 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6653 } else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) {
6654 // Request for full wake is removed while system is waking up to full wake
6655 DLOG("DisplayOn fullwake request is removed\n");
6656 handleSetDisplayPowerOn(false);
6657 }
6658
6659 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6660 pmPowerStateQueue->submitPowerEvent(
6661 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6662 }
6663 }
6664 }
6665
6666 //******************************************************************************
6667 // PM actions for graphics and audio.
6668 //******************************************************************************
6669
6670 void
6671 IOPMrootDomain::overridePowerChangeForService(
6672 IOService * service,
6673 IOPMActions * actions,
6674 const IOPMRequest * request,
6675 IOPMPowerStateIndex * inOutPowerState,
6676 IOPMPowerChangeFlags * inOutChangeFlags )
6677 {
6678 uint32_t powerState = (uint32_t) *inOutPowerState;
6679 uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6680 const uint32_t actionFlags = actions->flags;
6681
6682 if (kSystemTransitionNone == _systemTransitionType) {
6683 // Not in midst of a system transition.
6684 // Do not set kPMActionsStatePowerClamped.
6685 } else if ((actions->state & kPMActionsStatePowerClamped) == 0) {
6686 bool enableClamp = false;
6687
6688 // For most drivers, enable the clamp during ON->Dark transition
6689 // which has the kIOPMSynchronize flag set in changeFlags.
6690 if ((actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6691 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6692 (changeFlags & kIOPMSynchronize)) {
6693 enableClamp = true;
6694 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6695 ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6696 ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6697 (changeFlags & kIOPMSynchronize)) {
6698 enableClamp = true;
6699 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6700 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6701 (changeFlags & kIOPMSynchronize)) {
6702 enableClamp = true;
6703 } else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) &&
6704 (_systemTransitionType == kSystemTransitionSleep)) {
6705 // For graphics drivers, clamp power when entering
6706 // system sleep. Not when dropping to dark wake.
6707 enableClamp = true;
6708 }
6709
6710 if (enableClamp) {
6711 actions->state |= kPMActionsStatePowerClamped;
6712 DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6713 service->getName(), service->getRegistryEntryID(),
6714 _pendingCapability, powerState, changeFlags);
6715 }
6716 } else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6717 bool disableClamp = false;
6718
6719 if ((actionFlags & (
6720 kPMActionsFlagIsDisplayWrangler |
6721 kPMActionsFlagIsGraphicsDriver)) &&
6722 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6723 disableClamp = true;
6724 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6725 (_pendingCapability & kIOPMSystemCapabilityAudio)) {
6726 disableClamp = true;
6727 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6728 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6729 disableClamp = true;
6730 }
6731
6732 if (disableClamp) {
6733 actions->state &= ~kPMActionsStatePowerClamped;
6734 DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6735 service->getName(), service->getRegistryEntryID(),
6736 _pendingCapability, powerState, changeFlags);
6737 }
6738 }
6739
6740 if (actions->state & kPMActionsStatePowerClamped) {
6741 uint32_t maxPowerState = 0;
6742
6743 // Determine the max power state allowed when clamp is enabled
6744 if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
6745 // Parent intiated power state changes
6746 if ((service->getPowerState() > maxPowerState) &&
6747 (actionFlags & kPMActionsFlagIsDisplayWrangler)) {
6748 maxPowerState++;
6749
6750 // Remove lingering effects of any tickle before entering
6751 // dark wake. It will take a new tickle to return to full
6752 // wake, so the existing tickle state is useless.
6753
6754 if (changeFlags & kIOPMDomainDidChange) {
6755 *inOutChangeFlags |= kIOPMExpireIdleTimer;
6756 }
6757 } else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6758 maxPowerState++;
6759 } else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6760 maxPowerState = actions->darkWakePowerState;
6761 }
6762 } else {
6763 // Deny all self-initiated changes when power is limited.
6764 // Wrangler tickle should never defeat the limiter.
6765 maxPowerState = service->getPowerState();
6766 }
6767
6768 if (powerState > maxPowerState) {
6769 DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6770 service->getName(), service->getRegistryEntryID(),
6771 powerState, maxPowerState, changeFlags);
6772 *inOutPowerState = maxPowerState;
6773
6774 if (darkWakePostTickle &&
6775 (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6776 (changeFlags & kIOPMDomainWillChange) &&
6777 ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6778 kDarkWakeFlagPromotionEarly)) {
6779 darkWakePostTickle = false;
6780 reportUserInput();
6781 }
6782 }
6783
6784 if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
6785 if (darkWakeLogClamp) {
6786 AbsoluteTime now;
6787 uint64_t nsec;
6788
6789 clock_get_uptime(&now);
6790 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
6791 absolutetime_to_nanoseconds(now, &nsec);
6792 DLOG("dark wake power clamped after %u ms\n",
6793 ((int)((nsec) / NSEC_PER_MSEC)));
6794 }
6795 darkWakePowerClamped = true;
6796 }
6797 }
6798 }
6799
6800 void
6801 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6802 IOService * service,
6803 IOPMActions * actions )
6804 {
6805 #if DISPLAY_WRANGLER_PRESENT
6806 // Warning: Not running in PM work loop context - don't modify state !!!
6807 // Trap tickle directed to IODisplayWrangler while running with graphics
6808 // capability suppressed.
6809
6810 assert(service == wrangler);
6811
6812 clock_get_uptime(&userActivityTime);
6813 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
6814 || (lastSleepReason == kIOPMSleepReasonMaintenance)
6815 || (lastSleepReason == kIOPMSleepReasonSoftware));
6816 if (aborting) {
6817 userActivityCount++;
6818 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6819 userActivityCount, lastSleepReason);
6820 }
6821
6822 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
6823 DLOG("display wrangler tickled\n");
6824 if (kIOLogPMRootDomain & gIOKitDebug) {
6825 OSReportWithBacktrace("Dark wake display tickle");
6826 }
6827 if (pmPowerStateQueue) {
6828 pmPowerStateQueue->submitPowerEvent(
6829 kPowerEventPolicyStimulus,
6830 (void *) kStimulusDarkWakeActivityTickle,
6831 true /* set wake type */ );
6832 }
6833 }
6834 #endif /* DISPLAY_WRANGLER_PRESENT */
6835 }
6836
6837 void
6838 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6839 IOService * service,
6840 IOPMActions * actions,
6841 const OSSymbol * powerClient,
6842 IOPMPowerStateIndex oldPowerState,
6843 IOPMPowerStateIndex newPowerState )
6844 {
6845 #if DISPLAY_WRANGLER_PRESENT
6846 assert(service == wrangler);
6847
6848 // This function implements half of the user active detection
6849 // by monitoring changes to the display wrangler's device desire.
6850 //
6851 // User becomes active when either:
6852 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6853 // in max power state. This desire change in absence of a power state
6854 // change is detected within. This handles the case when user becomes
6855 // active while the display is already lit by setDisplayPowerOn().
6856 //
6857 // 2. Power state change to max, and DeviceDesire is also at max.
6858 // Handled by displayWranglerNotification().
6859 //
6860 // User becomes inactive when DeviceDesire drops to sleep state or below.
6861
6862 DLOG("wrangler %s (ps %u, %u->%u)\n",
6863 powerClient->getCStringNoCopy(),
6864 (uint32_t) service->getPowerState(),
6865 (uint32_t) oldPowerState, (uint32_t) newPowerState);
6866
6867 if (powerClient == gIOPMPowerClientDevice) {
6868 if ((newPowerState > oldPowerState) &&
6869 (newPowerState == kWranglerPowerStateMax) &&
6870 (service->getPowerState() == kWranglerPowerStateMax)) {
6871 evaluatePolicy( kStimulusEnterUserActiveState );
6872 } else if ((newPowerState < oldPowerState) &&
6873 (newPowerState <= kWranglerPowerStateSleep)) {
6874 evaluatePolicy( kStimulusLeaveUserActiveState );
6875 }
6876 }
6877
6878 if (newPowerState <= kWranglerPowerStateSleep) {
6879 evaluatePolicy( kStimulusDisplayWranglerSleep );
6880 } else if (newPowerState == kWranglerPowerStateMax) {
6881 evaluatePolicy( kStimulusDisplayWranglerWake );
6882 }
6883 #endif /* DISPLAY_WRANGLER_PRESENT */
6884 }
6885
6886 //******************************************************************************
6887 // User active state management
6888 //******************************************************************************
6889
6890 void
6891 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
6892 {
6893 #if DISPLAY_WRANGLER_PRESENT
6894 _preventUserActive = prevent;
6895 if (wrangler && !_preventUserActive) {
6896 // Allowing transition to user active, but the wrangler may have
6897 // already powered ON in case of sleep cancel/revert. Poll the
6898 // same conditions checked for in displayWranglerNotification()
6899 // to bring the user active state up to date.
6900
6901 if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
6902 (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
6903 kWranglerPowerStateMax)) {
6904 evaluatePolicy( kStimulusEnterUserActiveState );
6905 }
6906 }
6907 #endif /* DISPLAY_WRANGLER_PRESENT */
6908 }
6909
6910 //******************************************************************************
6911 // Approve usage of delayed child notification by PM.
6912 //******************************************************************************
6913
6914 bool
6915 IOPMrootDomain::shouldDelayChildNotification(
6916 IOService * service )
6917 {
6918 if ((kFullWakeReasonNone == fullWakeReason) &&
6919 (kSystemTransitionWake == _systemTransitionType)) {
6920 DLOG("%s: delay child notify\n", service->getName());
6921 return true;
6922 }
6923 return false;
6924 }
6925
6926 //******************************************************************************
6927 // PM actions for PCI device.
6928 //******************************************************************************
6929
6930 void
6931 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6932 IOService * service,
6933 IOPMActions * actions,
6934 const IOPMRequest * request,
6935 IOPMPowerStateIndex powerState,
6936 IOPMPowerChangeFlags * inOutChangeFlags )
6937 {
6938 pmTracer->tracePCIPowerChange(
6939 PMTraceWorker::kPowerChangeStart,
6940 service, *inOutChangeFlags,
6941 (actions->flags & kPMActionsPCIBitNumberMask));
6942 }
6943
6944 void
6945 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6946 IOService * service,
6947 IOPMActions * actions,
6948 const IOPMRequest * request,
6949 IOPMPowerStateIndex powerState,
6950 IOPMPowerChangeFlags changeFlags )
6951 {
6952 pmTracer->tracePCIPowerChange(
6953 PMTraceWorker::kPowerChangeCompleted,
6954 service, changeFlags,
6955 (actions->flags & kPMActionsPCIBitNumberMask));
6956 }
6957
6958 //******************************************************************************
6959 // registerInterest
6960 //
6961 // Override IOService::registerInterest() for root domain clients.
6962 //******************************************************************************
6963
6964 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
6965 {
6966 friend class IOPMrootDomain;
6967 OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
6968
6969 protected:
6970 uint32_t ackTimeoutCnt;
6971 uint32_t msgType; // Last type seen by the message filter
6972 uint32_t lastSleepWakeMsgType;
6973 uint32_t msgIndex;
6974 uint32_t maxMsgDelayMS;
6975 uint32_t maxAckDelayMS;
6976 uint64_t msgAbsTime;
6977 uint64_t uuid0;
6978 uint64_t uuid1;
6979 OSSharedPtr<const OSSymbol> identifier;
6980 OSSharedPtr<const OSSymbol> clientName;
6981 };
6982
6983 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
6984
6985 OSSharedPtr<IONotifier>
6986 IOPMrootDomain::registerInterest(
6987 const OSSymbol * typeOfInterest,
6988 IOServiceInterestHandler handler,
6989 void * target, void * ref )
6990 {
6991 IOPMServiceInterestNotifier* notifier;
6992 bool isSystemCapabilityClient;
6993 bool isKernelCapabilityClient;
6994 IOReturn rc = kIOReturnError;
6995
6996 isSystemCapabilityClient = typeOfInterest &&
6997 typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
6998
6999 isKernelCapabilityClient = typeOfInterest &&
7000 typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
7001
7002 if (isSystemCapabilityClient) {
7003 typeOfInterest = gIOAppPowerStateInterest;
7004 }
7005
7006 notifier = new IOPMServiceInterestNotifier;
7007 if (!notifier) {
7008 return NULL;
7009 }
7010
7011 if (notifier->init()) {
7012 rc = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
7013 }
7014 if (rc != kIOReturnSuccess) {
7015 OSSafeReleaseNULL(notifier);
7016 return NULL;
7017 }
7018
7019 notifier->ackTimeoutCnt = 0;
7020
7021 if (pmPowerStateQueue) {
7022 if (isSystemCapabilityClient) {
7023 notifier->retain();
7024 if (pmPowerStateQueue->submitPowerEvent(
7025 kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
7026 notifier->release();
7027 }
7028 }
7029
7030 if (isKernelCapabilityClient) {
7031 notifier->retain();
7032 if (pmPowerStateQueue->submitPowerEvent(
7033 kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
7034 notifier->release();
7035 }
7036 }
7037 }
7038
7039 OSSharedPtr<OSData> data;
7040 uint8_t *uuid = NULL;
7041 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
7042 if (kext) {
7043 data = kext->copyUUID();
7044 }
7045 if (data && (data->getLength() == sizeof(uuid_t))) {
7046 uuid = (uint8_t *)(data->getBytesNoCopy());
7047
7048 notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
7049 ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
7050 ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
7051 notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
7052 ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
7053 ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
7054
7055 notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
7056 }
7057 return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
7058 }
7059
7060 //******************************************************************************
7061 // systemMessageFilter
7062 //
7063 //******************************************************************************
7064
7065 bool
7066 IOPMrootDomain::systemMessageFilter(
7067 void * object, void * arg1, void * arg2, void * arg3 )
7068 {
7069 const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
7070 bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
7071 bool isCapPowerd = (object == (void *) systemCapabilityNotifier.get());
7072 bool isCapClient = false;
7073 bool allow = false;
7074 OSBoolean **waitForReply = (typeof(waitForReply))arg3;
7075 IOPMServiceInterestNotifier *notifier;
7076
7077 notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
7078
7079 do {
7080 // When powerd and kernel priority clients register capability interest,
7081 // the power tree is sync'ed to inform those clients about the current
7082 // system capability. Only allow capability change messages during sync.
7083 if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
7084 (!isCapMsg || !_joinedCapabilityClients ||
7085 !_joinedCapabilityClients->containsObject((OSObject *) object))) {
7086 break;
7087 }
7088
7089 // Capability change message for powerd and kernel clients
7090 if (isCapMsg) {
7091 // Kernel priority clients
7092 if ((context->notifyType == kNotifyPriority) ||
7093 (context->notifyType == kNotifyCapabilityChangePriority)) {
7094 isCapClient = true;
7095 }
7096
7097 // powerd will maintain two client registrations with root domain.
7098 // isCapPowerd will be TRUE for any message targeting the powerd
7099 // exclusive (capability change) interest registration.
7100 if (isCapPowerd && (context->notifyType == kNotifyCapabilityChangeApps)) {
7101 isCapClient = true;
7102 }
7103 }
7104
7105 if (isCapClient) {
7106 IOPMSystemCapabilityChangeParameters * capArgs =
7107 (IOPMSystemCapabilityChangeParameters *) arg2;
7108
7109 if (kSystemTransitionNewCapClient == _systemTransitionType) {
7110 capArgs->fromCapabilities = 0;
7111 capArgs->toCapabilities = _currentCapability;
7112 capArgs->changeFlags = 0;
7113 } else {
7114 capArgs->fromCapabilities = _currentCapability;
7115 capArgs->toCapabilities = _pendingCapability;
7116
7117 if (context->isPreChange) {
7118 capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
7119 } else {
7120 capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
7121 }
7122
7123 if (isCapPowerd && context->isPreChange) {
7124 toldPowerdCapWillChange = true;
7125 }
7126 }
7127
7128 // App level capability change messages must only go to powerd.
7129 // Wait for response post-change if capabilitiy is increasing.
7130 // Wait for response pre-change if capability is decreasing.
7131
7132 if ((context->notifyType == kNotifyCapabilityChangeApps) && waitForReply &&
7133 ((capabilityLoss && context->isPreChange) ||
7134 (!capabilityLoss && !context->isPreChange))) {
7135 *waitForReply = kOSBooleanTrue;
7136 }
7137
7138 allow = true;
7139 break;
7140 }
7141
7142 // powerd will always receive CanSystemSleep, even for a demand sleep.
7143 // It will also have a final chance to veto sleep after all clients
7144 // have responded to SystemWillSleep
7145
7146 if ((kIOMessageCanSystemSleep == context->messageType) ||
7147 (kIOMessageSystemWillNotSleep == context->messageType)) {
7148 if (isCapPowerd) {
7149 allow = true;
7150 break;
7151 }
7152
7153 // Demand sleep, don't ask apps for permission
7154 if (context->changeFlags & kIOPMSkipAskPowerDown) {
7155 break;
7156 }
7157 }
7158
7159 if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
7160 if (isCapPowerd && CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
7161 (fullToDarkReason == kIOPMSleepReasonIdle)) {
7162 allow = true;
7163 }
7164 break;
7165 }
7166
7167 // Drop capability change messages for legacy clients.
7168 // Drop legacy system sleep messages for powerd capability interest.
7169 if (isCapMsg || isCapPowerd) {
7170 break;
7171 }
7172
7173 // Not a capability change message.
7174 // Perform message filtering based on _systemMessageClientMask.
7175
7176 if ((context->notifyType == kNotifyApps) &&
7177 (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7178 if (!notifier) {
7179 break;
7180 }
7181
7182 if ((notifier->lastSleepWakeMsgType == context->messageType) &&
7183 (notifier->lastSleepWakeMsgType == kIOMessageSystemWillPowerOn)) {
7184 break; // drop any duplicate WillPowerOn for AOT devices
7185 }
7186
7187 allow = true;
7188
7189 if (waitForReply) {
7190 if (notifier->ackTimeoutCnt >= 3) {
7191 *waitForReply = kOSBooleanFalse;
7192 } else {
7193 *waitForReply = kOSBooleanTrue;
7194 }
7195 }
7196 } else if ((context->notifyType == kNotifyPriority) &&
7197 (_systemMessageClientMask & kSystemMessageClientKernel)) {
7198 allow = true;
7199 }
7200
7201 // Check sleep/wake message ordering
7202 if (allow) {
7203 if (context->messageType == kIOMessageSystemWillSleep ||
7204 context->messageType == kIOMessageSystemWillPowerOn ||
7205 context->messageType == kIOMessageSystemHasPoweredOn) {
7206 notifier->lastSleepWakeMsgType = context->messageType;
7207 }
7208 }
7209 } while (false);
7210
7211 if (allow && isCapMsg && _joinedCapabilityClients) {
7212 _joinedCapabilityClients->removeObject((OSObject *) object);
7213 if (_joinedCapabilityClients->getCount() == 0) {
7214 DMSG("destroyed capability client set %p\n",
7215 OBFUSCATE(_joinedCapabilityClients.get()));
7216 _joinedCapabilityClients.reset();
7217 }
7218 }
7219 if (notifier) {
7220 // Record the last seen message type even if the message is dropped
7221 // for traceFilteredNotification().
7222 notifier->msgType = context->messageType;
7223 }
7224
7225 return allow;
7226 }
7227
7228 //******************************************************************************
7229 // setMaintenanceWakeCalendar
7230 //
7231 //******************************************************************************
7232
7233 IOReturn
7234 IOPMrootDomain::setMaintenanceWakeCalendar(
7235 const IOPMCalendarStruct * calendar )
7236 {
7237 OSSharedPtr<OSData> data;
7238 IOReturn ret = 0;
7239
7240 if (!calendar) {
7241 return kIOReturnBadArgument;
7242 }
7243
7244 data = OSData::withValue(*calendar);
7245 if (!data) {
7246 return kIOReturnNoMemory;
7247 }
7248
7249 if (kPMCalendarTypeMaintenance == calendar->selector) {
7250 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get());
7251 } else if (kPMCalendarTypeSleepService == calendar->selector) {
7252 ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get());
7253 }
7254
7255 return ret;
7256 }
7257
7258 // MARK: -
7259 // MARK: Display Wrangler
7260
7261 //******************************************************************************
7262 // displayWranglerNotification
7263 //
7264 // Handle the notification when the IODisplayWrangler changes power state.
7265 //******************************************************************************
7266
7267 IOReturn
7268 IOPMrootDomain::displayWranglerNotification(
7269 void * target, void * refCon,
7270 UInt32 messageType, IOService * service,
7271 void * messageArgument, vm_size_t argSize )
7272 {
7273 #if DISPLAY_WRANGLER_PRESENT
7274 IOPMPowerStateIndex displayPowerState;
7275 IOPowerStateChangeNotification * params =
7276 (IOPowerStateChangeNotification *) messageArgument;
7277
7278 if ((messageType != kIOMessageDeviceWillPowerOff) &&
7279 (messageType != kIOMessageDeviceHasPoweredOn)) {
7280 return kIOReturnUnsupported;
7281 }
7282
7283 ASSERT_GATED();
7284 if (!gRootDomain) {
7285 return kIOReturnUnsupported;
7286 }
7287
7288 displayPowerState = params->stateNumber;
7289 DLOG("wrangler %s ps %d\n",
7290 getIOMessageString(messageType), (uint32_t) displayPowerState);
7291
7292 switch (messageType) {
7293 case kIOMessageDeviceWillPowerOff:
7294 // Display wrangler has dropped power due to display idle
7295 // or force system sleep.
7296 //
7297 // 4 Display ON kWranglerPowerStateMax
7298 // 3 Display Dim kWranglerPowerStateDim
7299 // 2 Display Sleep kWranglerPowerStateSleep
7300 // 1 Not visible to user
7301 // 0 Not visible to user kWranglerPowerStateMin
7302
7303 if (displayPowerState <= kWranglerPowerStateSleep) {
7304 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7305 }
7306 break;
7307
7308 case kIOMessageDeviceHasPoweredOn:
7309 // Display wrangler has powered on due to user activity
7310 // or wake from sleep.
7311
7312 if (kWranglerPowerStateMax == displayPowerState) {
7313 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7314
7315 // See comment in handleUpdatePowerClientForDisplayWrangler
7316 if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7317 kWranglerPowerStateMax) {
7318 gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7319 }
7320 }
7321 break;
7322 }
7323 #endif /* DISPLAY_WRANGLER_PRESENT */
7324 return kIOReturnUnsupported;
7325 }
7326
7327 //******************************************************************************
7328 // reportUserInput
7329 //
7330 //******************************************************************************
7331
7332 void
7333 IOPMrootDomain::updateUserActivity( void )
7334 {
7335 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7336 clock_get_uptime(&userActivityTime);
7337 bool aborting = ((lastSleepReason == kIOPMSleepReasonSoftware)
7338 || (lastSleepReason == kIOPMSleepReasonIdle)
7339 || (lastSleepReason == kIOPMSleepReasonMaintenance));
7340 if (aborting) {
7341 userActivityCount++;
7342 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7343 }
7344 #endif
7345 }
7346 void
7347 IOPMrootDomain::reportUserInput( void )
7348 {
7349 if (wrangler) {
7350 wrangler->activityTickle(0, 0);
7351 }
7352 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7353 // Update user activity
7354 updateUserActivity();
7355
7356 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7357 // update user active abs time
7358 clock_get_uptime(&gUserActiveAbsTime);
7359 pmPowerStateQueue->submitPowerEvent(
7360 kPowerEventPolicyStimulus,
7361 (void *) kStimulusDarkWakeActivityTickle,
7362 true /* set wake type */ );
7363 }
7364 #endif
7365 }
7366
7367 void
7368 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7369 {
7370 #if DISPLAY_WRANGLER_PRESENT
7371 if (wrangler) {
7372 wrangler->activityTickle(0, 0);
7373 }
7374 #else
7375 if (!device) {
7376 DLOG("requestUserActive: device is null\n");
7377 return;
7378 }
7379 OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7380 uint64_t registryID = device->getRegistryEntryID();
7381
7382 if (!deviceName || !registryID) {
7383 DLOG("requestUserActive: no device name or registry entry\n");
7384 return;
7385 }
7386 const char *name = deviceName->getCStringNoCopy();
7387 char payload[128];
7388 snprintf(payload, sizeof(payload), "%s:%s", name, reason);
7389 DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason);
7390 messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload));
7391 #endif
7392 }
7393
7394 //******************************************************************************
7395 // latchDisplayWranglerTickle
7396 //******************************************************************************
7397
7398 bool
7399 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7400 {
7401 #if DISPLAY_WRANGLER_PRESENT
7402 if (latch) {
7403 if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
7404 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7405 !checkSystemCanSustainFullWake()) {
7406 // Currently in dark wake, and not transitioning to full wake.
7407 // Full wake is unsustainable, so latch the tickle to prevent
7408 // the display from lighting up momentarily.
7409 wranglerTickled = true;
7410 } else {
7411 wranglerTickled = false;
7412 }
7413 } else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7414 wranglerTickled = false;
7415
7416 pmPowerStateQueue->submitPowerEvent(
7417 kPowerEventPolicyStimulus,
7418 (void *) kStimulusDarkWakeActivityTickle );
7419 }
7420
7421 return wranglerTickled;
7422 #else /* ! DISPLAY_WRANGLER_PRESENT */
7423 return false;
7424 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7425 }
7426
7427 //******************************************************************************
7428 // setDisplayPowerOn
7429 //
7430 // For root domain user client
7431 //******************************************************************************
7432
7433 void
7434 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7435 {
7436 pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7437 (void *) NULL, options );
7438 }
7439
7440 // MARK: -
7441 // MARK: System PM Policy
7442
7443 //******************************************************************************
7444 // checkSystemSleepAllowed
7445 //
7446 //******************************************************************************
7447
7448 bool
7449 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7450 uint32_t sleepReason )
7451 {
7452 uint32_t err = 0;
7453
7454 // Conditions that prevent idle and demand system sleep.
7455
7456 do {
7457 if (gSleepDisabledFlag) {
7458 err = kPMConfigPreventSystemSleep;
7459 break;
7460 }
7461
7462 if (userDisabledAllSleep) {
7463 err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7464 break;
7465 }
7466
7467 if (systemBooting || systemShutdown || gWillShutdown) {
7468 err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7469 break;
7470 }
7471
7472 if (options == 0) {
7473 break;
7474 }
7475
7476 // Conditions above pegs the system at full wake.
7477 // Conditions below prevent system sleep but does not prevent
7478 // dark wake, and must be called from gated context.
7479
7480 #if !CONFIG_SLEEP
7481 err = kPMConfigPreventSystemSleep; // 3. config does not support sleep
7482 break;
7483 #endif
7484
7485 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7486 break; // always sleep on low battery or when in thermal warning/emergency state
7487 }
7488
7489 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7490 break; // always sleep on dark wake thermal emergencies
7491 }
7492
7493 if (preventSystemSleepList->getCount() != 0) {
7494 err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7495 break;
7496 }
7497
7498 if (_driverKitMatchingAssertionCount != 0) {
7499 err = kPMCPUAssertion;
7500 break;
7501 }
7502
7503 // Check for any dexts currently being added to the PM tree. Sleeping while
7504 // this is in flight can cause IOServicePH to timeout.
7505 if (!IOServicePH::checkPMReady()) {
7506 #if !defined(XNU_TARGET_OS_OSX)
7507 // 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
7508 // in dark wake for long periods of time, which causes issues as apps were
7509 // already informed of sleep during the f->9 transition. As a temporary
7510 // measure, always full wake if we hit this specific condition.
7511 pmPowerStateQueue->submitPowerEvent(
7512 kPowerEventPolicyStimulus,
7513 (void *) kStimulusDarkWakeActivityTickle);
7514 #endif
7515 err = kPMDKNotReady;
7516 break;
7517 }
7518
7519 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7520 kIOPMDriverAssertionLevelOn) {
7521 err = kPMCPUAssertion; // 5. CPU assertion
7522 break;
7523 }
7524
7525 if (pciCantSleepValid) {
7526 if (pciCantSleepFlag) {
7527 err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7528 }
7529 break;
7530 } else if (sleepSupportedPEFunction &&
7531 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7532 IOReturn ret;
7533 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7534 ret = getPlatform()->callPlatformFunction(
7535 sleepSupportedPEFunction.get(), false,
7536 NULL, NULL, NULL, NULL);
7537 pciCantSleepValid = true;
7538 pciCantSleepFlag = false;
7539 if ((platformSleepSupport & kPCICantSleep) ||
7540 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7541 err = 6; // 6. PCI card does not support PM
7542 pciCantSleepFlag = true;
7543 break;
7544 }
7545 }
7546 }while (false);
7547
7548 if (err) {
7549 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7550 return false;
7551 }
7552 return true;
7553 }
7554
7555 bool
7556 IOPMrootDomain::checkSystemSleepEnabled( void )
7557 {
7558 return checkSystemSleepAllowed(0, 0);
7559 }
7560
7561 bool
7562 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7563 {
7564 ASSERT_GATED();
7565 return checkSystemSleepAllowed(1, sleepReason);
7566 }
7567
7568 //******************************************************************************
7569 // checkSystemCanSustainFullWake
7570 //******************************************************************************
7571
7572 bool
7573 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7574 {
7575 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7576 // Low battery wake, or received a low battery notification
7577 // while system is awake. This condition will persist until
7578 // the following wake.
7579 return false;
7580 }
7581
7582 if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7583 // Graphics state is unknown and external display might not be probed.
7584 // Do not incorporate state that requires graphics to be in max power
7585 // such as desktopMode or clamshellDisabled.
7586
7587 if (!acAdaptorConnected) {
7588 DLOG("full wake check: no AC\n");
7589 return false;
7590 }
7591 }
7592 return true;
7593 }
7594
7595 //******************************************************************************
7596 // mustHibernate
7597 //******************************************************************************
7598
7599 #if HIBERNATION
7600
7601 bool
7602 IOPMrootDomain::mustHibernate( void )
7603 {
7604 return lowBatteryCondition || thermalWarningState;
7605 }
7606
7607 #endif /* HIBERNATION */
7608
7609 //******************************************************************************
7610 // AOT
7611 //******************************************************************************
7612
7613 // Tables for accumulated days in year by month, latter used for leap years
7614
7615 static const unsigned int daysbymonth[] =
7616 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7617
7618 static const unsigned int lydaysbymonth[] =
7619 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7620
7621 static int __unused
7622 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7623 {
7624 const unsigned int * dbm = daysbymonth;
7625 clock_sec_t n, x, y, z;
7626
7627 // Calculate seconds, minutes and hours
7628
7629 n = secs % (24 * 3600);
7630 dt->second = n % 60;
7631 n /= 60;
7632 dt->minute = n % 60;
7633 dt->hour = (typeof(dt->hour))(n / 60);
7634
7635 // Calculate day of week
7636
7637 n = secs / (24 * 3600);
7638 // dt->dayWeek = (n + 4) % 7;
7639
7640 // Calculate year
7641 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7642 // to days since 1/1/1968 to start on 4 year cycle, beginning
7643 // on a leap year.
7644
7645 n += (366 + 365);
7646
7647 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7648 // Valid before 2100, since 2100 is not a leap year.
7649
7650 x = n / 1461; // number of 4 year cycles
7651 y = n % 1461; // days into current 4 year cycle
7652 z = 1968 + (4 * x);
7653
7654 // Add in years in the current 4 year cycle
7655
7656 if (y >= 366) {
7657 y -= 366; // days after the leap year
7658 n = y % 365; // days into the current year
7659 z += (1 + y / 365); // years after the past 4-yr cycle
7660 } else {
7661 n = y;
7662 dbm = lydaysbymonth;
7663 }
7664 if (z > 2099) {
7665 return 0;
7666 }
7667
7668 dt->year = (typeof(dt->year))z;
7669
7670 // Adjust remaining days value to start at 1
7671
7672 n += 1;
7673
7674 // Calculate month
7675
7676 for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7677 continue;
7678 }
7679 dt->month = (typeof(dt->month))x;
7680
7681 // Calculate day of month
7682
7683 dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7684
7685 return 1;
7686 }
7687
7688 static clock_sec_t
7689 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7690 {
7691 const unsigned int * dbm = daysbymonth;
7692 long y, secs, days;
7693
7694 if (dt->year < 1970 || dt->month > 12) {
7695 return 0;
7696 }
7697
7698 // Seconds elapsed in the current day
7699
7700 secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7701
7702 // Number of days from 1/1/70 to beginning of current year
7703 // Account for extra day every 4 years starting at 1973
7704
7705 y = dt->year - 1970;
7706 days = (y * 365) + ((y + 1) / 4);
7707
7708 // Change table if current year is a leap year
7709
7710 if ((dt->year % 4) == 0) {
7711 dbm = lydaysbymonth;
7712 }
7713
7714 // Add in days elapsed in the current year
7715
7716 days += (dt->day - 1) + dbm[dt->month - 1];
7717
7718 // Add accumulated days to accumulated seconds
7719
7720 secs += 24 * 3600 * days;
7721
7722 return secs;
7723 }
7724
7725 unsigned long
7726 IOPMrootDomain::getRUN_STATE(void)
7727 {
7728 return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
7729 }
7730
7731 bool
7732 IOPMrootDomain::isAOTMode()
7733 {
7734 return _aotNow;
7735 }
7736
7737 IOReturn
7738 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7739 {
7740 clock_sec_t nowsecs, wakesecs;
7741 clock_usec_t nowmicrosecs, wakemicrosecs;
7742 uint64_t nowAbs, wakeAbs;
7743
7744 if (!_aotMode) {
7745 return kIOReturnNotReady;
7746 }
7747
7748 clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
7749 wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
7750 if (wakeAbs < nowAbs) {
7751 printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
7752 wakeAbs = nowAbs;
7753 }
7754 wakeAbs -= nowAbs;
7755 absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7756
7757 wakesecs += nowsecs;
7758 wakemicrosecs += nowmicrosecs;
7759 if (wakemicrosecs >= USEC_PER_SEC) {
7760 wakesecs++;
7761 wakemicrosecs -= USEC_PER_SEC;
7762 }
7763 if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7764 wakesecs++;
7765 }
7766
7767 IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7768
7769 if (_aotWakeTimeContinuous != wakeContinuousTime) {
7770 _aotWakeTimeContinuous = wakeContinuousTime;
7771 IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7772 }
7773 _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7774 _aotWakeTimeUTC = wakesecs;
7775
7776 return kIOReturnSuccess;
7777 }
7778
7779 // assumes WAKEEVENT_LOCK
7780 bool
7781 IOPMrootDomain::aotShouldExit(bool checkTimeSet, bool software)
7782 {
7783 bool exitNow = false;
7784 const char * reason = "";
7785
7786 if (!_aotNow) {
7787 return false;
7788 }
7789
7790 if (software) {
7791 exitNow = true;
7792 _aotMetrics->softwareRequestCount++;
7793 reason = "software request";
7794 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7795 exitNow = true;
7796 reason = gWakeReasonString;
7797 } else if (checkTimeSet && (kPMCalendarTypeInvalid == _aotWakeTimeCalendar.selector)) {
7798 exitNow = true;
7799 _aotMetrics->noTimeSetCount++;
7800 reason = "flipbook expired";
7801 } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7802 clock_sec_t sec;
7803 clock_usec_t usec;
7804 clock_get_calendar_microtime(&sec, &usec);
7805 if (_calendarWakeAlarmUTC <= sec) {
7806 exitNow = true;
7807 _aotMetrics->rtcAlarmsCount++;
7808 reason = "user alarm";
7809 }
7810 }
7811 if (exitNow) {
7812 _aotPendingFlags |= kIOPMWakeEventAOTExit;
7813 IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7814 reason,
7815 _aotMetrics->sleepCount,
7816 _aotMetrics->possibleCount,
7817 _aotMetrics->confirmedPossibleCount,
7818 _aotMetrics->rejectedPossibleCount,
7819 _aotMetrics->expiredPossibleCount,
7820 _aotMetrics->noTimeSetCount,
7821 _aotMetrics->rtcAlarmsCount);
7822 }
7823 return exitNow;
7824 }
7825
7826 void
7827 IOPMrootDomain::aotExit(bool cps)
7828 {
7829 uint32_t savedMessageMask;
7830
7831 ASSERT_GATED();
7832 _aotNow = false;
7833 _aotReadyToFullWake = false;
7834 if (_aotTimerScheduled) {
7835 _aotTimerES->cancelTimeout();
7836 _aotTimerScheduled = false;
7837 }
7838 updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
7839
7840 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7841 _aotLastWakeTime = 0;
7842 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7843 WAKEEVENT_LOCK();
7844 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7845 gWakeReasonString,
7846 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7847 WAKEEVENT_UNLOCK();
7848 }
7849
7850 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7851
7852 // Preserve the message mask since a system wake transition
7853 // may have already started and initialized the mask.
7854 savedMessageMask = _systemMessageClientMask;
7855 _systemMessageClientMask = kSystemMessageClientLegacyApp;
7856 tellClients(kIOMessageSystemWillPowerOn);
7857 _systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
7858
7859 if (cps) {
7860 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7861 }
7862 }
7863
7864 void
7865 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7866 {
7867 bool exitNow;
7868
7869 IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7870
7871 WAKEEVENT_LOCK();
7872 exitNow = aotShouldExit(false, false);
7873 if (timer != NULL) {
7874 _aotTimerScheduled = false;
7875 }
7876 WAKEEVENT_UNLOCK();
7877 if (exitNow) {
7878 aotExit(true);
7879 } else {
7880 #if 0
7881 if (_aotLingerTime) {
7882 uint64_t deadline;
7883 IOLog("aot linger before sleep\n");
7884 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7885 clock_delay_until(deadline);
7886 }
7887 #endif
7888 privateSleepSystem(kIOPMSleepReasonSoftware);
7889 }
7890 }
7891
7892 //******************************************************************************
7893 // adjustPowerState
7894 //
7895 // Conditions that affect our wake/sleep decision has changed.
7896 // If conditions dictate that the system must remain awake, clamp power
7897 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7898 // is TRUE, then remove the power clamp and allow the power state to drop
7899 // to SLEEP_STATE.
7900 //******************************************************************************
7901
7902 void
7903 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7904 {
7905 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7906 getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7907
7908 ASSERT_GATED();
7909
7910 if (_aotNow) {
7911 bool exitNow;
7912
7913 if (AOT_STATE != getPowerState()) {
7914 return;
7915 }
7916 WAKEEVENT_LOCK();
7917 exitNow = aotShouldExit(true, false);
7918 if (!exitNow
7919 && !_aotTimerScheduled
7920 && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
7921 _aotTimerScheduled = true;
7922 if (_aotLingerTime) {
7923 _aotTimerES->setTimeout(_aotLingerTime);
7924 } else {
7925 _aotTimerES->setTimeout(800, kMillisecondScale);
7926 }
7927 }
7928 WAKEEVENT_UNLOCK();
7929 if (exitNow) {
7930 aotExit(true);
7931 } else {
7932 _aotReadyToFullWake = true;
7933 if (!_aotTimerScheduled) {
7934 if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
7935 // Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
7936 // Doing so will result in the sleep being cancelled anyway,
7937 // but this check avoids unnecessary thrashing in the power state engine.
7938 return;
7939 }
7940 privateSleepSystem(kIOPMSleepReasonSoftware);
7941 }
7942 }
7943 return;
7944 }
7945
7946 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
7947 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
7948 } else if (sleepASAP) {
7949 changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
7950 }
7951 }
7952
7953 void
7954 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
7955 {
7956 if (powerOn) {
7957 if (!checkSystemCanSustainFullWake()) {
7958 DLOG("System cannot sustain full wake\n");
7959 return;
7960 }
7961
7962 // Force wrangler to max power state. If system is in dark wake
7963 // this alone won't raise the wrangler's power state.
7964 if (wrangler) {
7965 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
7966 }
7967
7968 // System in dark wake, always requesting full wake should
7969 // not have any bad side-effects, even if the request fails.
7970
7971 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
7972 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
7973 requestFullWake( kFullWakeReasonDisplayOn );
7974 }
7975 } else {
7976 // Relenquish desire to power up display.
7977 // Must first transition to state 1 since wrangler doesn't
7978 // power off the displays at state 0. At state 0 the root
7979 // domain is removed from the wrangler's power client list.
7980 if (wrangler) {
7981 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
7982 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
7983 }
7984 }
7985 }
7986
7987 //******************************************************************************
7988 // dispatchPowerEvent
7989 //
7990 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
7991 //******************************************************************************
7992
7993 void
7994 IOPMrootDomain::dispatchPowerEvent(
7995 uint32_t event, void * arg0, uint64_t arg1 )
7996 {
7997 ASSERT_GATED();
7998
7999 switch (event) {
8000 case kPowerEventFeatureChanged:
8001 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8002 messageClients(kIOPMMessageFeatureChange, this);
8003 break;
8004
8005 case kPowerEventReceivedPowerNotification:
8006 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8007 handlePowerNotification((UInt32)(uintptr_t) arg0 );
8008 break;
8009
8010 case kPowerEventSystemBootCompleted:
8011 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8012 if (systemBooting) {
8013 systemBooting = false;
8014
8015 if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
8016 DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
8017 }
8018 if (lowBatteryCondition || thermalEmergencyState) {
8019 if (lowBatteryCondition) {
8020 privateSleepSystem(kIOPMSleepReasonLowPower);
8021 } else {
8022 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8023 }
8024 // The rest is unnecessary since the system is expected
8025 // to sleep immediately. The following wake will update
8026 // everything.
8027 break;
8028 }
8029
8030 sleepWakeDebugMemAlloc();
8031 saveFailureData2File();
8032
8033 // If lid is closed, re-send lid closed notification
8034 // now that booting is complete.
8035 if (clamshellClosed) {
8036 handlePowerNotification(kLocalEvalClamshellCommand);
8037 }
8038 evaluatePolicy( kStimulusAllowSystemSleepChanged );
8039 }
8040 break;
8041
8042 case kPowerEventSystemShutdown:
8043 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8044 if (kOSBooleanTrue == (OSBoolean *) arg0) {
8045 /* We set systemShutdown = true during shutdown
8046 * to prevent sleep at unexpected times while loginwindow is trying
8047 * to shutdown apps and while the OS is trying to transition to
8048 * complete power of.
8049 *
8050 * Set to true during shutdown, as soon as loginwindow shows
8051 * the "shutdown countdown dialog", through individual app
8052 * termination, and through black screen kernel shutdown.
8053 */
8054 systemShutdown = true;
8055 } else {
8056 /*
8057 * A shutdown was initiated, but then the shutdown
8058 * was cancelled, clearing systemShutdown to false here.
8059 */
8060 systemShutdown = false;
8061 }
8062 break;
8063
8064 case kPowerEventUserDisabledSleep:
8065 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8066 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8067 break;
8068
8069 case kPowerEventRegisterSystemCapabilityClient:
8070 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8071
8072 // reset() handles the arg0 == nullptr case for us
8073 systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8074 /* intentional fall-through */
8075 [[clang::fallthrough]];
8076
8077 case kPowerEventRegisterKernelCapabilityClient:
8078 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8079 if (!_joinedCapabilityClients) {
8080 _joinedCapabilityClients = OSSet::withCapacity(8);
8081 }
8082 if (arg0) {
8083 OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8084 if (_joinedCapabilityClients) {
8085 _joinedCapabilityClients->setObject(notify.get());
8086 synchronizePowerTree( kIOPMSyncNoChildNotify );
8087 }
8088 }
8089 break;
8090
8091 case kPowerEventPolicyStimulus:
8092 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8093 if (arg0) {
8094 int stimulus = (int)(uintptr_t) arg0;
8095 evaluatePolicy(stimulus, (uint32_t) arg1);
8096 }
8097 break;
8098
8099 case kPowerEventAssertionCreate:
8100 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8101 if (pmAssertions) {
8102 pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8103 }
8104 break;
8105
8106
8107 case kPowerEventAssertionRelease:
8108 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8109 if (pmAssertions) {
8110 pmAssertions->handleReleaseAssertion(arg1);
8111 }
8112 break;
8113
8114 case kPowerEventAssertionSetLevel:
8115 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8116 if (pmAssertions) {
8117 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8118 }
8119 break;
8120
8121 case kPowerEventQueueSleepWakeUUID:
8122 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8123 handleQueueSleepWakeUUID((OSObject *)arg0);
8124 break;
8125 case kPowerEventPublishSleepWakeUUID:
8126 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8127 handlePublishSleepWakeUUID((bool)arg0);
8128 break;
8129
8130 case kPowerEventSetDisplayPowerOn:
8131 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8132 if (arg1 != 0) {
8133 displayPowerOnRequested = true;
8134 } else {
8135 displayPowerOnRequested = false;
8136 }
8137 handleSetDisplayPowerOn(displayPowerOnRequested);
8138 break;
8139
8140 case kPowerEventPublishWakeType:
8141 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8142
8143 // Don't replace wake type property if already set
8144 if ((arg0 == gIOPMWakeTypeUserKey) ||
8145 !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8146 const char * wakeType = NULL;
8147
8148 if (arg0 == gIOPMWakeTypeUserKey) {
8149 requestUserActive(this, "WakeTypeUser");
8150 wakeType = kIOPMRootDomainWakeTypeUser;
8151 } else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8152 if (!(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
8153 requestUserActive(this, "WakeTypeAlarm");
8154 }
8155 wakeType = kIOPMRootDomainWakeTypeAlarm;
8156 } else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8157 darkWakeSleepService = true;
8158 wakeType = kIOPMRootDomainWakeTypeSleepService;
8159 } else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8160 wakeType = kIOPMRootDomainWakeTypeMaintenance;
8161 }
8162
8163 if (wakeType) {
8164 setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8165 }
8166 }
8167 break;
8168
8169 case kPowerEventAOTEvaluate:
8170 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8171 if (_aotReadyToFullWake) {
8172 aotEvaluate(NULL);
8173 }
8174 break;
8175 }
8176 }
8177
8178 //******************************************************************************
8179 // systemPowerEventOccurred
8180 //
8181 // The power controller is notifying us of a hardware-related power management
8182 // event that we must handle.
8183 //
8184 // systemPowerEventOccurred covers the same functionality that
8185 // receivePowerNotification does; it simply provides a richer API for conveying
8186 // more information.
8187 //******************************************************************************
8188
8189 IOReturn
8190 IOPMrootDomain::systemPowerEventOccurred(
8191 const OSSymbol *event,
8192 uint32_t intValue)
8193 {
8194 IOReturn attempt = kIOReturnSuccess;
8195 OSSharedPtr<OSNumber> newNumber;
8196
8197 if (!event) {
8198 return kIOReturnBadArgument;
8199 }
8200
8201 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8202 if (!newNumber) {
8203 return kIOReturnInternalError;
8204 }
8205
8206 attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8207
8208 return attempt;
8209 }
8210
8211 void
8212 IOPMrootDomain::setThermalState(OSObject *value)
8213 {
8214 OSNumber * num;
8215
8216 if (gIOPMWorkLoop->inGate() == false) {
8217 gIOPMWorkLoop->runAction(
8218 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8219 (OSObject *)this,
8220 (void *)value);
8221
8222 return;
8223 }
8224 if (value && (num = OSDynamicCast(OSNumber, value))) {
8225 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8226 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8227 }
8228 }
8229
8230 IOReturn
8231 IOPMrootDomain::systemPowerEventOccurred(
8232 const OSSymbol *event,
8233 OSObject *value)
8234 {
8235 OSSharedPtr<OSDictionary> thermalsDict;
8236 bool shouldUpdate = true;
8237
8238 if (!event || !value) {
8239 return kIOReturnBadArgument;
8240 }
8241
8242 // LOCK
8243 // We reuse featuresDict Lock because it already exists and guards
8244 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
8245 // of stepping on that lock.
8246 if (featuresDictLock) {
8247 IOLockLock(featuresDictLock);
8248 }
8249
8250 OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8251 OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8252
8253 if (origThermalsDict) {
8254 thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8255 } else {
8256 thermalsDict = OSDictionary::withCapacity(1);
8257 }
8258
8259 if (!thermalsDict) {
8260 shouldUpdate = false;
8261 goto exit;
8262 }
8263
8264 thermalsDict->setObject(event, value);
8265
8266 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8267
8268 exit:
8269 // UNLOCK
8270 if (featuresDictLock) {
8271 IOLockUnlock(featuresDictLock);
8272 }
8273
8274 if (shouldUpdate) {
8275 if (event &&
8276 event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8277 setThermalState(value);
8278 }
8279 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8280 }
8281
8282 return kIOReturnSuccess;
8283 }
8284
8285 //******************************************************************************
8286 // receivePowerNotification
8287 //
8288 // The power controller is notifying us of a hardware-related power management
8289 // event that we must handle. This may be a result of an 'environment' interrupt
8290 // from the power mgt micro.
8291 //******************************************************************************
8292
8293 IOReturn
8294 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8295 {
8296 if (msg & kIOPMPowerButton) {
8297 uint32_t currentPhase = pmTracer->getTracePhase();
8298 if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8299 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8300 swd_flags |= SWD_PWR_BTN_STACKSHOT;
8301 thread_call_enter(powerButtonDown);
8302 } else {
8303 DEBUG_LOG("power button pressed when system is up\n");
8304 }
8305 } else if (msg & kIOPMPowerButtonUp) {
8306 if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8307 swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8308 thread_call_enter(powerButtonUp);
8309 }
8310 } else {
8311 pmPowerStateQueue->submitPowerEvent(
8312 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8313 }
8314 return kIOReturnSuccess;
8315 }
8316
8317 void
8318 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8319 {
8320 bool eval_clamshell = false;
8321 bool eval_clamshell_alarm = false;
8322
8323 ASSERT_GATED();
8324
8325 /*
8326 * Local (IOPMrootDomain only) eval clamshell command
8327 */
8328 if (msg & kLocalEvalClamshellCommand) {
8329 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8330 eval_clamshell_alarm = true;
8331
8332 // reset isRTCAlarmWake. This evaluation should happen only once
8333 // on RTC/Alarm wake. Any clamshell events after wake should follow
8334 // the regular evaluation
8335 isRTCAlarmWake = false;
8336 } else {
8337 eval_clamshell = true;
8338 }
8339 }
8340
8341 /*
8342 * Overtemp
8343 */
8344 if (msg & kIOPMOverTemp) {
8345 DLOG("Thermal overtemp message received!\n");
8346 thermalEmergencyState = true;
8347 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8348 }
8349
8350 /*
8351 * Forward DW thermal notification to client, if system is not going to sleep
8352 */
8353 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8354 DLOG("DarkWake thermal limits message received!\n");
8355 messageClients(kIOPMMessageDarkWakeThermalEmergency);
8356 }
8357
8358 /*
8359 * Sleep Now!
8360 */
8361 if (msg & kIOPMSleepNow) {
8362 privateSleepSystem(kIOPMSleepReasonSoftware);
8363 }
8364
8365 /*
8366 * Power Emergency
8367 */
8368 if (msg & kIOPMPowerEmergency) {
8369 DLOG("Received kIOPMPowerEmergency");
8370 lowBatteryCondition = true;
8371 privateSleepSystem(kIOPMSleepReasonLowPower);
8372 }
8373
8374 /*
8375 * Clamshell OPEN
8376 */
8377 if (msg & kIOPMClamshellOpened) {
8378 DLOG("Clamshell opened\n");
8379 // Received clamshel open message from clamshell controlling driver
8380 // Update our internal state and tell general interest clients
8381 clamshellClosed = false;
8382 clamshellExists = true;
8383
8384 // Don't issue a hid tickle when lid is open and polled on wake
8385 if (msg & kIOPMSetValue) {
8386 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8387 reportUserInput();
8388 }
8389
8390 // Tell PMCPU
8391 informCPUStateChange(kInformLid, 0);
8392
8393 // Tell general interest clients
8394 sendClientClamshellNotification();
8395
8396 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
8397 || (lastSleepReason == kIOPMSleepReasonIdle)
8398 || (lastSleepReason == kIOPMSleepReasonMaintenance));
8399 if (aborting) {
8400 userActivityCount++;
8401 }
8402 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8403 }
8404
8405 /*
8406 * Clamshell CLOSED
8407 * Send the clamshell interest notification since the lid is closing.
8408 */
8409 if (msg & kIOPMClamshellClosed) {
8410 if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8411 clamshellClosed && clamshellExists) {
8412 DLOG("Ignoring redundant Clamshell close event\n");
8413 } else {
8414 DLOG("Clamshell closed\n");
8415 // Received clamshel open message from clamshell controlling driver
8416 // Update our internal state and tell general interest clients
8417 clamshellClosed = true;
8418 clamshellExists = true;
8419
8420 // Ignore all following clamshell close events until the clamshell
8421 // is opened or the system sleeps. When a clamshell close triggers
8422 // a system wake, the lid driver may send us two clamshell close
8423 // events, one for the clamshell close event itself, and a second
8424 // close event when the driver polls the lid state on wake.
8425 clamshellIgnoreClose = true;
8426
8427 // Tell PMCPU
8428 informCPUStateChange(kInformLid, 1);
8429
8430 // Tell general interest clients
8431 sendClientClamshellNotification();
8432
8433 // And set eval_clamshell = so we can attempt
8434 eval_clamshell = true;
8435 }
8436 }
8437
8438 /*
8439 * Set Desktop mode (sent from graphics)
8440 *
8441 * -> reevaluate lid state
8442 */
8443 if (msg & kIOPMSetDesktopMode) {
8444 desktopMode = (0 != (msg & kIOPMSetValue));
8445 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8446 DLOG("Desktop mode %d\n", desktopMode);
8447
8448 sendClientClamshellNotification();
8449
8450 // Re-evaluate the lid state
8451 eval_clamshell = true;
8452 }
8453
8454 /*
8455 * AC Adaptor connected
8456 *
8457 * -> reevaluate lid state
8458 */
8459 if (msg & kIOPMSetACAdaptorConnected) {
8460 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8461 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8462
8463 // Tell CPU PM
8464 informCPUStateChange(kInformAC, !acAdaptorConnected);
8465
8466 // Tell BSD if AC is connected
8467 // 0 == external power source; 1 == on battery
8468 post_sys_powersource(acAdaptorConnected ? 0:1);
8469
8470 sendClientClamshellNotification();
8471
8472 IOUserServer::powerSourceChanged(acAdaptorConnected);
8473
8474 // Re-evaluate the lid state
8475 eval_clamshell = true;
8476
8477 // Lack of AC may have latched a display wrangler tickle.
8478 // This mirrors the hardware's USB wake event latch, where a latched
8479 // USB wake event followed by an AC attach will trigger a full wake.
8480 latchDisplayWranglerTickle( false );
8481
8482 #if HIBERNATION
8483 // AC presence will reset the standy timer delay adjustment.
8484 _standbyTimerResetSeconds = 0;
8485 #endif
8486 if (!userIsActive) {
8487 // Reset userActivityTime when power supply is changed(rdr 13789330)
8488 clock_get_uptime(&userActivityTime);
8489 }
8490 }
8491
8492 /*
8493 * Enable Clamshell (external display disappear)
8494 *
8495 * -> reevaluate lid state
8496 */
8497 if (msg & kIOPMEnableClamshell) {
8498 DLOG("Clamshell enabled\n");
8499
8500 // Re-evaluate the lid state
8501 // System should sleep on external display disappearance
8502 // in lid closed operation.
8503 if (true == clamshellDisabled) {
8504 eval_clamshell = true;
8505
8506 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8507 // Also clear kClamshellSleepDisableInternal when graphics enables
8508 // the clamshell during a full wake. When graphics is behaving as
8509 // expected, this will allow clamshell close to be honored earlier
8510 // rather than waiting for the delayed evaluation.
8511 if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8512 (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8513 CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8514 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8515
8516 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8517 // when timer expires which is harmless but useless.
8518 thread_call_cancel(fullWakeThreadCall);
8519 }
8520 #endif
8521 }
8522
8523 clamshellDisabled = false;
8524 sendClientClamshellNotification();
8525 }
8526
8527 /*
8528 * Disable Clamshell (external display appeared)
8529 * We don't bother re-evaluating clamshell state. If the system is awake,
8530 * the lid is probably open.
8531 */
8532 if (msg & kIOPMDisableClamshell) {
8533 DLOG("Clamshell disabled\n");
8534 clamshellDisabled = true;
8535 sendClientClamshellNotification();
8536 }
8537
8538 /*
8539 * Evaluate clamshell and SLEEP if appropriate
8540 */
8541 if (eval_clamshell_alarm && clamshellClosed) {
8542 if (shouldSleepOnRTCAlarmWake()) {
8543 privateSleepSystem(kIOPMSleepReasonClamshell);
8544 }
8545 } else if (eval_clamshell && clamshellClosed) {
8546 if (shouldSleepOnClamshellClosed()) {
8547 privateSleepSystem(kIOPMSleepReasonClamshell);
8548 } else {
8549 evaluatePolicy( kStimulusDarkWakeEvaluate );
8550 }
8551 }
8552
8553 if (msg & kIOPMProModeEngaged) {
8554 int newState = 1;
8555 DLOG("ProModeEngaged\n");
8556 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8557 }
8558
8559 if (msg & kIOPMProModeDisengaged) {
8560 int newState = 0;
8561 DLOG("ProModeDisengaged\n");
8562 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8563 }
8564 }
8565
8566 //******************************************************************************
8567 // evaluatePolicy
8568 //
8569 // Evaluate root-domain policy in response to external changes.
8570 //******************************************************************************
8571
8572 void
8573 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8574 {
8575 union {
8576 struct {
8577 int idleSleepEnabled : 1;
8578 int idleSleepDisabled : 1;
8579 int displaySleep : 1;
8580 int sleepDelayChanged : 1;
8581 int evaluateDarkWake : 1;
8582 int adjustPowerState : 1;
8583 int userBecameInactive : 1;
8584 int displaySleepEntry : 1;
8585 } bit;
8586 uint32_t u32;
8587 } flags;
8588
8589
8590 ASSERT_GATED();
8591 flags.u32 = 0;
8592
8593 switch (stimulus) {
8594 case kStimulusDisplayWranglerSleep:
8595 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8596 if (!wranglerPowerOff) {
8597 // wrangler is in sleep state or lower
8598 flags.bit.displaySleep = true;
8599 }
8600 if (!wranglerAsleep) {
8601 // transition from wrangler wake to wrangler sleep
8602 flags.bit.displaySleepEntry = true;
8603 wranglerAsleep = true;
8604 }
8605 break;
8606
8607 case kStimulusDisplayWranglerWake:
8608 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8609 displayIdleForDemandSleep = false;
8610 wranglerPowerOff = false;
8611 wranglerAsleep = false;
8612 break;
8613
8614 case kStimulusEnterUserActiveState:
8615 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8616 if (_preventUserActive) {
8617 DLOG("user active dropped\n");
8618 break;
8619 }
8620 if (!userIsActive) {
8621 userIsActive = true;
8622 userWasActive = true;
8623 clock_get_uptime(&gUserActiveAbsTime);
8624
8625 // Stay awake after dropping demand for display power on
8626 if (kFullWakeReasonDisplayOn == fullWakeReason) {
8627 fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8628 DLOG("User activity while in notification wake\n");
8629 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8630 }
8631
8632 kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8633 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8634 messageClients(kIOPMMessageUserIsActiveChanged);
8635 }
8636 flags.bit.idleSleepDisabled = true;
8637 break;
8638
8639 case kStimulusLeaveUserActiveState:
8640 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8641 if (userIsActive) {
8642 clock_get_uptime(&gUserInactiveAbsTime);
8643 userIsActive = false;
8644 clock_get_uptime(&userBecameInactiveTime);
8645 flags.bit.userBecameInactive = true;
8646
8647 kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8648 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8649 messageClients(kIOPMMessageUserIsActiveChanged);
8650 }
8651 break;
8652
8653 case kStimulusAggressivenessChanged:
8654 {
8655 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8656 unsigned long aggressiveValue;
8657 uint32_t minutesToIdleSleep = 0;
8658 uint32_t minutesToDisplayDim = 0;
8659 uint32_t minutesDelta = 0;
8660
8661 // Fetch latest display and system sleep slider values.
8662 aggressiveValue = 0;
8663 getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8664 minutesToIdleSleep = (uint32_t) aggressiveValue;
8665
8666 aggressiveValue = 0;
8667 getAggressiveness(kPMMinutesToDim, &aggressiveValue);
8668 minutesToDisplayDim = (uint32_t) aggressiveValue;
8669 DLOG("aggressiveness changed: system %u->%u, display %u\n",
8670 sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
8671
8672 DLOG("idle time -> %d ms (ena %d)\n",
8673 idleMilliSeconds, (minutesToIdleSleep != 0));
8674
8675 // How long to wait before sleeping the system once
8676 // the displays turns off is indicated by 'extraSleepDelay'.
8677
8678 if (minutesToIdleSleep > minutesToDisplayDim) {
8679 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8680 } else if (minutesToIdleSleep == minutesToDisplayDim) {
8681 minutesDelta = 1;
8682 }
8683
8684 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8685 idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8686 }
8687
8688 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8689 flags.bit.idleSleepDisabled = true;
8690 idleSleepEnabled = false;
8691 }
8692 #if !defined(XNU_TARGET_OS_OSX)
8693 if (0x7fffffff == minutesToIdleSleep) {
8694 minutesToIdleSleep = idleMilliSeconds / 1000;
8695 }
8696 #endif /* !defined(XNU_TARGET_OS_OSX) */
8697
8698 if (((minutesDelta != extraSleepDelay) ||
8699 (userActivityTime != userActivityTime_prev)) &&
8700 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8701 flags.bit.sleepDelayChanged = true;
8702 }
8703
8704 if (systemDarkWake && !darkWakeToSleepASAP &&
8705 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8706 // Reconsider decision to remain in dark wake
8707 flags.bit.evaluateDarkWake = true;
8708 }
8709
8710 sleepSlider = minutesToIdleSleep;
8711 extraSleepDelay = minutesDelta;
8712 userActivityTime_prev = userActivityTime;
8713 } break;
8714
8715 case kStimulusDemandSystemSleep:
8716 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8717 displayIdleForDemandSleep = true;
8718 if (wrangler && wranglerIdleSettings) {
8719 // Request wrangler idle only when demand sleep is triggered
8720 // from full wake.
8721 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8722 wrangler->setProperties(wranglerIdleSettings.get());
8723 DLOG("Requested wrangler idle\n");
8724 }
8725 }
8726 // arg = sleepReason
8727 changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8728 break;
8729
8730 case kStimulusAllowSystemSleepChanged:
8731 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8732 flags.bit.adjustPowerState = true;
8733 break;
8734
8735 case kStimulusDarkWakeActivityTickle:
8736 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8737 // arg == true implies real and not self generated wrangler tickle.
8738 // Update wake type on PM work loop instead of the tickle thread to
8739 // eliminate the possibility of an early tickle clobbering the wake
8740 // type set by the platform driver.
8741 if (arg == true) {
8742 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8743 }
8744
8745 if (!darkWakeExit) {
8746 if (latchDisplayWranglerTickle(true)) {
8747 DLOG("latched tickle\n");
8748 break;
8749 }
8750
8751 darkWakeExit = true;
8752 DLOG("Requesting full wake due to dark wake activity tickle\n");
8753 requestFullWake( kFullWakeReasonLocalUser );
8754 }
8755 break;
8756
8757 case kStimulusDarkWakeEntry:
8758 case kStimulusDarkWakeReentry:
8759 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8760 // Any system transitions since the last dark wake transition
8761 // will invalid the stimulus.
8762
8763 if (arg == _systemStateGeneration) {
8764 DLOG("dark wake entry\n");
8765 systemDarkWake = true;
8766
8767 // Keep wranglerPowerOff an invariant when wrangler is absent
8768 if (wrangler) {
8769 wranglerPowerOff = true;
8770 }
8771
8772 if (kStimulusDarkWakeEntry == stimulus) {
8773 clock_get_uptime(&userBecameInactiveTime);
8774 flags.bit.evaluateDarkWake = true;
8775 if (activitySinceSleep()) {
8776 DLOG("User activity recorded while going to darkwake\n");
8777 reportUserInput();
8778 }
8779 }
8780
8781 // Always accelerate disk spindown while in dark wake,
8782 // even if system does not support/allow sleep.
8783
8784 cancelIdleSleepTimer();
8785 setQuickSpinDownTimeout();
8786 }
8787 break;
8788
8789 case kStimulusDarkWakeEvaluate:
8790 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8791 if (systemDarkWake) {
8792 flags.bit.evaluateDarkWake = true;
8793 }
8794 break;
8795
8796 case kStimulusNoIdleSleepPreventers:
8797 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8798 flags.bit.adjustPowerState = true;
8799 break;
8800 } /* switch(stimulus) */
8801
8802 if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
8803 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8804 darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
8805 if (darkWakeToSleepASAP ||
8806 (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
8807 uint32_t newSleepReason;
8808
8809 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8810 // System was previously in full wake. Sleep reason from
8811 // full to dark already recorded in fullToDarkReason.
8812
8813 if (lowBatteryCondition) {
8814 newSleepReason = kIOPMSleepReasonLowPower;
8815 } else if (thermalEmergencyState) {
8816 newSleepReason = kIOPMSleepReasonThermalEmergency;
8817 } else {
8818 newSleepReason = fullToDarkReason;
8819 }
8820 } else {
8821 // In dark wake from system sleep.
8822
8823 if (darkWakeSleepService) {
8824 newSleepReason = kIOPMSleepReasonSleepServiceExit;
8825 } else {
8826 newSleepReason = kIOPMSleepReasonMaintenance;
8827 }
8828 }
8829
8830 if (checkSystemCanSleep(newSleepReason)) {
8831 privateSleepSystem(newSleepReason);
8832 }
8833 } else { // non-maintenance (network) dark wake
8834 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8835 // Release power clamp, and wait for children idle.
8836 adjustPowerState(true);
8837 } else {
8838 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8839 }
8840 }
8841 }
8842
8843 if (systemDarkWake) {
8844 // The rest are irrelevant while system is in dark wake.
8845 flags.u32 = 0;
8846 }
8847
8848 if ((flags.bit.displaySleepEntry) &&
8849 (kFullWakeReasonDisplayOn == fullWakeReason)) {
8850 // kIOPMSleepReasonNotificationWakeExit
8851 DLOG("Display sleep while in notification wake\n");
8852 changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8853 }
8854
8855 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8856 bool cancelQuickSpindown = false;
8857
8858 if (flags.bit.sleepDelayChanged) {
8859 // Cancel existing idle sleep timer and quick disk spindown.
8860 // New settings will be applied by the idleSleepEnabled flag
8861 // handler below if idle sleep is enabled.
8862
8863 DLOG("extra sleep timer changed\n");
8864 cancelIdleSleepTimer();
8865 cancelQuickSpindown = true;
8866 } else {
8867 DLOG("user inactive\n");
8868 }
8869
8870 if (!userIsActive && idleSleepEnabled) {
8871 startIdleSleepTimer(getTimeToIdleSleep());
8872 }
8873
8874 if (cancelQuickSpindown) {
8875 restoreUserSpinDownTimeout();
8876 }
8877 }
8878
8879 if (flags.bit.idleSleepEnabled) {
8880 DLOG("idle sleep timer enabled\n");
8881 if (!wrangler) {
8882 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8883 startIdleSleepTimer(getTimeToIdleSleep());
8884 #else
8885 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8886 startIdleSleepTimer( idleMilliSeconds );
8887 #endif
8888 } else {
8889 // Start idle timer if prefs now allow system sleep
8890 // and user is already inactive. Disk spindown is
8891 // accelerated upon timer expiration.
8892
8893 if (!userIsActive) {
8894 startIdleSleepTimer(getTimeToIdleSleep());
8895 }
8896 }
8897 }
8898
8899 if (flags.bit.idleSleepDisabled) {
8900 DLOG("idle sleep timer disabled\n");
8901 cancelIdleSleepTimer();
8902 restoreUserSpinDownTimeout();
8903 adjustPowerState();
8904 }
8905
8906 if (flags.bit.adjustPowerState) {
8907 bool sleepASAP = false;
8908
8909 if (!systemBooting && (0 == idleSleepPreventersCount())) {
8910 if (!wrangler) {
8911 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
8912 if (idleSleepEnabled) {
8913 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8914 if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
8915 sleepASAP = true;
8916 }
8917 #else
8918 // stay awake for at least idleMilliSeconds
8919 startIdleSleepTimer(idleMilliSeconds);
8920 #endif
8921 }
8922 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
8923 sleepASAP = true;
8924 }
8925 }
8926
8927 adjustPowerState(sleepASAP);
8928 }
8929 }
8930
8931 //******************************************************************************
8932
8933 unsigned int
8934 IOPMrootDomain::idleSleepPreventersCount()
8935 {
8936 if (_aotMode) {
8937 unsigned int count __block;
8938 count = 0;
8939 preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
8940 {
8941 count += (NULL == obj->metaCast("AppleARMBacklight"));
8942 return false;
8943 });
8944 return count;
8945 }
8946
8947 return preventIdleSleepList->getCount();
8948 }
8949
8950
8951 //******************************************************************************
8952 // requestFullWake
8953 //
8954 // Request transition from dark wake to full wake
8955 //******************************************************************************
8956
8957 void
8958 IOPMrootDomain::requestFullWake( FullWakeReason reason )
8959 {
8960 uint32_t options = 0;
8961 IOService * pciRoot = NULL;
8962 bool promotion = false;
8963
8964 // System must be in dark wake and a valid reason for entering full wake
8965 if ((kFullWakeReasonNone == reason) ||
8966 (kFullWakeReasonNone != fullWakeReason) ||
8967 (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8968 return;
8969 }
8970
8971 // Will clear reason upon exit from full wake
8972 fullWakeReason = reason;
8973
8974 _desiredCapability |= (kIOPMSystemCapabilityGraphics |
8975 kIOPMSystemCapabilityAudio);
8976
8977 if ((kSystemTransitionWake == _systemTransitionType) &&
8978 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
8979 !darkWakePowerClamped) {
8980 // Promote to full wake while waking up to dark wake due to tickle.
8981 // PM will hold off notifying the graphics subsystem about system wake
8982 // as late as possible, so if a HID tickle does arrive, graphics can
8983 // power up from this same wake transition. Otherwise, the latency to
8984 // power up graphics on the following transition can be huge on certain
8985 // systems. However, once any power clamping has taken effect, it is
8986 // too late to promote the current dark wake transition to a full wake.
8987 _pendingCapability |= (kIOPMSystemCapabilityGraphics |
8988 kIOPMSystemCapabilityAudio);
8989
8990 // Tell the PCI parent of audio and graphics drivers to stop
8991 // delaying the child notifications. Same for root domain.
8992 pciRoot = pciHostBridgeDriver.get();
8993 willEnterFullWake();
8994 promotion = true;
8995 }
8996
8997 // Unsafe to cancel once graphics was powered.
8998 // If system woke from dark wake, the return to sleep can
8999 // be cancelled. "awake -> dark -> sleep" transition
9000 // can be cancelled also, during the "dark -> sleep" phase
9001 // *prior* to driver power down.
9002 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
9003 _pendingCapability == 0) {
9004 options |= kIOPMSyncCancelPowerDown;
9005 }
9006
9007 synchronizePowerTree(options, pciRoot);
9008
9009 if (kFullWakeReasonLocalUser == fullWakeReason) {
9010 // IOGraphics doesn't light the display even though graphics is
9011 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
9012 // So, do an explicit activity tickle
9013 if (wrangler) {
9014 wrangler->activityTickle(0, 0);
9015 }
9016 }
9017
9018 // Log a timestamp for the initial full wake request.
9019 // System may not always honor this full wake request.
9020 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9021 AbsoluteTime now;
9022 uint64_t nsec;
9023
9024 clock_get_uptime(&now);
9025 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9026 absolutetime_to_nanoseconds(now, &nsec);
9027 MSG("full wake %s (reason %u) %u ms\n",
9028 promotion ? "promotion" : "request",
9029 fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9030 }
9031 }
9032
9033 //******************************************************************************
9034 // willEnterFullWake
9035 //
9036 // System will enter full wake from sleep, from dark wake, or from dark
9037 // wake promotion. This function aggregate things that are in common to
9038 // all three full wake transitions.
9039 //
9040 // Assumptions: fullWakeReason was updated
9041 //******************************************************************************
9042
9043 void
9044 IOPMrootDomain::willEnterFullWake( void )
9045 {
9046 hibernateRetry = false;
9047 sleepToStandby = false;
9048 standbyNixed = false;
9049 resetTimers = false;
9050 sleepTimerMaintenance = false;
9051
9052 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9053
9054 _systemMessageClientMask = kSystemMessageClientPowerd |
9055 kSystemMessageClientLegacyApp;
9056
9057 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9058 // First time to attain full wake capability since the last wake
9059 _systemMessageClientMask |= kSystemMessageClientKernel;
9060
9061 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9062 setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9063 (kFullWakeReasonLocalUser == fullWakeReason) ?
9064 kOSBooleanTrue : kOSBooleanFalse);
9065 }
9066 #if HIBERNATION
9067 IOHibernateSetWakeCapabilities(_pendingCapability);
9068 #endif
9069
9070 IOService::setAdvisoryTickleEnable( true );
9071 tellClients(kIOMessageSystemWillPowerOn);
9072 preventTransitionToUserActive(false);
9073 }
9074
9075 //******************************************************************************
9076 // fullWakeDelayedWork
9077 //
9078 // System has already entered full wake. Invoked by a delayed thread call.
9079 //******************************************************************************
9080
9081 void
9082 IOPMrootDomain::fullWakeDelayedWork( void )
9083 {
9084 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9085 if (!gIOPMWorkLoop->inGate()) {
9086 gIOPMWorkLoop->runAction(
9087 OSMemberFunctionCast(IOWorkLoop::Action, this,
9088 &IOPMrootDomain::fullWakeDelayedWork), this);
9089 return;
9090 }
9091
9092 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9093 _currentCapability, _pendingCapability, _highestCapability,
9094 clamshellDisabled, clamshellSleepDisableMask);
9095
9096 if (clamshellExists &&
9097 CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9098 !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9099 if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9100 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9101 } else {
9102 // Not the initial full wake after waking from sleep.
9103 // Evaluate the clamshell for rdar://problem/9157444.
9104 receivePowerNotification(kLocalEvalClamshellCommand);
9105 }
9106 }
9107 #endif
9108 }
9109
9110 //******************************************************************************
9111 // evaluateAssertions
9112 //
9113 //******************************************************************************
9114
9115 // Bitmask of all kernel assertions that prevent system idle sleep.
9116 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9117 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9118 (kIOPMDriverAssertionReservedBit7 | \
9119 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9120
9121 void
9122 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9123 {
9124 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9125
9126 messageClients(kIOPMMessageDriverAssertionsChanged);
9127
9128 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9129 if (wrangler) {
9130 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9131
9132 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9133 wrangler->setIgnoreIdleTimer( value );
9134 }
9135 }
9136
9137 if (changedBits & kIOPMDriverAssertionCPUBit) {
9138 if (_aotNow) {
9139 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9140 }
9141 evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9142 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9143 AbsoluteTime now;
9144 clock_usec_t microsecs;
9145 clock_get_uptime(&now);
9146 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9147 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
9148 if (assertOnWakeReport) {
9149 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9150 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9151 }
9152 }
9153 }
9154
9155 if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9156 if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9157 if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9158 DLOG("PreventIdleSleep driver assertion raised\n");
9159 bool ok = updatePreventIdleSleepList(this, true);
9160 if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9161 // Cancel idle sleep if there is one in progress
9162 cancelIdlePowerDown(this);
9163 }
9164 }
9165 } else {
9166 DLOG("PreventIdleSleep driver assertion dropped\n");
9167 updatePreventIdleSleepList(this, false);
9168 }
9169 }
9170 }
9171
9172 // MARK: -
9173 // MARK: Statistics
9174
9175 //******************************************************************************
9176 // pmStats
9177 //
9178 //******************************************************************************
9179
9180 void
9181 IOPMrootDomain::pmStatsRecordEvent(
9182 int eventIndex,
9183 AbsoluteTime timestamp)
9184 {
9185 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9186 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9187 uint64_t delta;
9188 uint64_t nsec;
9189 OSSharedPtr<OSData> publishPMStats;
9190
9191 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9192
9193 absolutetime_to_nanoseconds(timestamp, &nsec);
9194
9195 switch (eventIndex) {
9196 case kIOPMStatsHibernateImageWrite:
9197 if (starting) {
9198 gPMStats.hibWrite.start = nsec;
9199 } else if (stopping) {
9200 gPMStats.hibWrite.stop = nsec;
9201 }
9202
9203 if (stopping) {
9204 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9205 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9206 }
9207 break;
9208 case kIOPMStatsHibernateImageRead:
9209 if (starting) {
9210 gPMStats.hibRead.start = nsec;
9211 } else if (stopping) {
9212 gPMStats.hibRead.stop = nsec;
9213 }
9214
9215 if (stopping) {
9216 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9217 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9218
9219 publishPMStats = OSData::withValue(gPMStats);
9220 setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9221 bzero(&gPMStats, sizeof(gPMStats));
9222 }
9223 break;
9224 }
9225 }
9226
9227 /*
9228 * Appends a record of the application response to
9229 * IOPMrootDomain::pmStatsAppResponses
9230 */
9231 void
9232 IOPMrootDomain::pmStatsRecordApplicationResponse(
9233 const OSSymbol *response,
9234 const char *name,
9235 int messageType,
9236 uint32_t delay_ms,
9237 uint64_t id,
9238 OSObject *object,
9239 IOPMPowerStateIndex powerState,
9240 bool async)
9241 {
9242 OSSharedPtr<OSDictionary> responseDescription;
9243 OSSharedPtr<OSNumber> delayNum;
9244 OSSharedPtr<OSNumber> powerCaps;
9245 OSSharedPtr<OSNumber> pidNum;
9246 OSSharedPtr<OSNumber> msgNum;
9247 OSSharedPtr<const OSSymbol> appname;
9248 OSSharedPtr<const OSSymbol> sleep;
9249 OSSharedPtr<const OSSymbol> wake;
9250 IOPMServiceInterestNotifier *notify = NULL;
9251
9252 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9253 if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9254 notify->ackTimeoutCnt++;
9255 } else {
9256 notify->ackTimeoutCnt = 0;
9257 }
9258 }
9259
9260 if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9261 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9262 return;
9263 }
9264
9265
9266 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9267 kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9268 } else if (notify) {
9269 // User space app or kernel capability client
9270 if (id) {
9271 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9272 } else {
9273 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9274 }
9275 notify->msgType = 0;
9276 }
9277
9278 responseDescription = OSDictionary::withCapacity(5);
9279 if (responseDescription) {
9280 if (response) {
9281 responseDescription->setObject(_statsResponseTypeKey.get(), response);
9282 }
9283
9284 msgNum = OSNumber::withNumber(messageType, 32);
9285 if (msgNum) {
9286 responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9287 }
9288
9289 if (!name && notify && notify->identifier) {
9290 name = notify->identifier->getCStringNoCopy();
9291 }
9292
9293 if (name && (strlen(name) > 0)) {
9294 appname = OSSymbol::withCString(name);
9295 if (appname) {
9296 responseDescription->setObject(_statsNameKey.get(), appname.get());
9297 }
9298 }
9299
9300 if (!id && notify) {
9301 id = notify->uuid0;
9302 }
9303 pidNum = OSNumber::withNumber(id, 64);
9304 if (pidNum) {
9305 responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9306 }
9307
9308 delayNum = OSNumber::withNumber(delay_ms, 32);
9309 if (delayNum) {
9310 responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9311 }
9312
9313 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9314 powerCaps = OSNumber::withNumber(powerState, 32);
9315
9316 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9317 static const char * driverCallTypes[] = {
9318 [kDriverCallInformPreChange] = "powerStateWillChangeTo",
9319 [kDriverCallInformPostChange] = "powerStateDidChangeTo",
9320 [kDriverCallSetPowerState] = "setPowerState"
9321 };
9322
9323 if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9324 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9325 name, id, driverCallTypes[messageType], (uint32_t) powerState,
9326 async ? "async " : "", delay_ms);
9327 }
9328 #endif
9329 } else {
9330 powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9331 }
9332 if (powerCaps) {
9333 responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9334 }
9335
9336 sleep = OSSymbol::withCString("Sleep");
9337 wake = OSSymbol::withCString("Wake");
9338 if (_systemTransitionType == kSystemTransitionSleep) {
9339 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9340 } else if (_systemTransitionType == kSystemTransitionWake) {
9341 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9342 } else if (_systemTransitionType == kSystemTransitionCapability) {
9343 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9344 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9345 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9346 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9347 }
9348 }
9349
9350 IOLockLock(pmStatsLock);
9351 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9352 pmStatsAppResponses->setObject(responseDescription.get());
9353 }
9354 IOLockUnlock(pmStatsLock);
9355 }
9356
9357 return;
9358 }
9359
9360 // MARK: -
9361 // MARK: PMTraceWorker
9362
9363 //******************************************************************************
9364 // TracePoint support
9365 //
9366 //******************************************************************************
9367
9368 #define kIOPMRegisterNVRAMTracePointHandlerKey \
9369 "IOPMRegisterNVRAMTracePointHandler"
9370
9371 IOReturn
9372 IOPMrootDomain::callPlatformFunction(
9373 const OSSymbol * functionName,
9374 bool waitForFunction,
9375 void * param1, void * param2,
9376 void * param3, void * param4 )
9377 {
9378 if (pmTracer && functionName &&
9379 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9380 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9381 uint32_t tracePointPhases, tracePointPCI;
9382 uint64_t statusCode;
9383
9384 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9385 pmTracer->tracePointTarget = (void *) param2;
9386 tracePointPCI = (uint32_t)(uintptr_t) param3;
9387 tracePointPhases = (uint32_t)(uintptr_t) param4;
9388 if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9389 OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9390 if (node) {
9391 OSSharedPtr<OSObject> bootRomFailureProp;
9392 bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9393 OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9394 uint32_t bootFailureCode;
9395 if (data && data->getLength() == sizeof(bootFailureCode)) {
9396 // Failure code from EFI/BootRom is a four byte structure
9397 memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9398 tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9399 }
9400 }
9401 }
9402 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9403 if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9404 MSG("Sleep failure code 0x%08x 0x%08x\n",
9405 tracePointPCI, tracePointPhases);
9406 }
9407 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9408 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9409
9410 return kIOReturnSuccess;
9411 }
9412 #if HIBERNATION
9413 else if (functionName &&
9414 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9415 if (gSleepPolicyHandler) {
9416 return kIOReturnExclusiveAccess;
9417 }
9418 if (!param1) {
9419 return kIOReturnBadArgument;
9420 }
9421 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9422 gSleepPolicyTarget = (void *) param2;
9423 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9424 return kIOReturnSuccess;
9425 }
9426 #endif
9427
9428 return super::callPlatformFunction(
9429 functionName, waitForFunction, param1, param2, param3, param4);
9430 }
9431
9432 void
9433 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9434 uintptr_t param1, uintptr_t param2, uintptr_t param3)
9435 {
9436 uint32_t code = IODBG_POWER(event);
9437 uint64_t regId = id;
9438 if (regId == 0) {
9439 regId = getRegistryEntryID();
9440 }
9441 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9442 }
9443
9444 void
9445 IOPMrootDomain::tracePoint( uint8_t point )
9446 {
9447 if (systemBooting) {
9448 return;
9449 }
9450
9451 if (kIOPMTracePointWakeCapabilityClients == point) {
9452 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9453 }
9454
9455 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9456 pmTracer->tracePoint(point);
9457 }
9458
9459 static void
9460 kext_log_putc(char c)
9461 {
9462 if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9463 return;
9464 }
9465 if (c == '(' || c == '[' || c == ' ') {
9466 c = 0;
9467 gKextNameEnd = true;
9468 }
9469
9470 gKextNameBuf[gKextNamePos++] = c;
9471 }
9472
9473 static int
9474 kext_log(const char *fmt, ...)
9475 {
9476 va_list listp;
9477
9478 va_start(listp, fmt);
9479 _doprnt(fmt, &listp, &kext_log_putc, 16);
9480 va_end(listp);
9481
9482 return 0;
9483 }
9484
9485 static OSPtr<const OSSymbol>
9486 copyKextIdentifierWithAddress(vm_address_t address)
9487 {
9488 OSSharedPtr<const OSSymbol> identifer;
9489
9490 IOLockLock(gHaltLogLock);
9491
9492 gKextNameEnd = false;
9493 gKextNamePos = 0;
9494 gKextNameBuf[0] = 0;
9495
9496 OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9497 gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9498 identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9499
9500 IOLockUnlock(gHaltLogLock);
9501
9502 return identifer;
9503 }
9504
9505 // Caller serialized using PM workloop
9506 const char *
9507 IOPMrootDomain::getNotificationClientName(OSObject *object)
9508 {
9509 IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9510 const char *clientName = "UNKNOWN";
9511
9512 if (!notifier->clientName) {
9513 // Check for user client
9514 if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9515 OSNumber *clientID = NULL;
9516 messageClient(kIOMessageCopyClientID, object, &clientID);
9517 if (clientID) {
9518 OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9519 if (string) {
9520 notifier->clientName = OSSymbol::withString(string.get());
9521 }
9522 clientID->release();
9523 }
9524 } else if (notifier->identifier) {
9525 notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9526 }
9527 }
9528
9529 if (notifier->clientName) {
9530 clientName = notifier->clientName->getCStringNoCopy();
9531 }
9532
9533 return clientName;
9534 }
9535
9536 void
9537 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9538 {
9539 IOPMServiceInterestNotifier *notifier;
9540
9541 if (systemBooting) {
9542 return;
9543 }
9544 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9545 if (!notifier) {
9546 return;
9547 }
9548
9549 if (start) {
9550 pmTracer->traceDetail(notifier->uuid0 >> 32);
9551 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9552 (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9553
9554 // Update notifier state used for response/ack logging
9555 notifier->msgIndex = msgIndex;
9556 notifier->msgAbsTime = timestamp;
9557
9558 if (msgIndex != UINT_MAX) {
9559 DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9560 } else {
9561 DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9562 }
9563
9564 assert(notifierObject == NULL);
9565 notifierThread = current_thread();
9566 notifierObject.reset(notifier, OSRetain);
9567 } else {
9568 uint64_t nsec;
9569 uint32_t delayMS;
9570
9571 SUB_ABSOLUTETIME(×tamp, ¬ifier->msgAbsTime);
9572 absolutetime_to_nanoseconds(timestamp, &nsec);
9573 delayMS = (uint32_t)(nsec / 1000000ULL);
9574 if (delayMS > notifier->maxMsgDelayMS) {
9575 notifier->maxMsgDelayMS = delayMS;
9576 }
9577
9578 assert(notifierObject == notifier);
9579 notifierObject.reset();
9580 notifierThread = NULL;
9581 }
9582 }
9583
9584 void
9585 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9586 {
9587 if (systemBooting) {
9588 return;
9589 }
9590 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9591 if (!notifier) {
9592 return;
9593 }
9594
9595 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9596 (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9597
9598 DLOG("%s[%u] ack from %s took %d ms\n",
9599 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9600 if (delay_ms > notifier->maxAckDelayMS) {
9601 notifier->maxAckDelayMS = delay_ms;
9602 }
9603 }
9604
9605 void
9606 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9607 {
9608 if (systemBooting) {
9609 return;
9610 }
9611 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9612 if (!notifier) {
9613 return;
9614 }
9615
9616 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9617 (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9618
9619 if (ack_time_us == 0) {
9620 // Client work is done and ack will not be forthcoming
9621 DLOG("%s[%u] response from %s took %d ms\n",
9622 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9623 } else {
9624 // Client needs more time and it must ack within ack_time_us
9625 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9626 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9627 }
9628 }
9629
9630 void
9631 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9632 {
9633 if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9634 return;
9635 }
9636 if (systemBooting) {
9637 return;
9638 }
9639 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9640 if (!notifier) {
9641 return;
9642 }
9643
9644 DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9645 }
9646
9647 void
9648 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9649 {
9650 if (!systemBooting) {
9651 uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
9652 pmTracer->traceDetail( detail );
9653 kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
9654 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
9655 }
9656 }
9657
9658 void
9659 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9660 {
9661 size_t reportSize;
9662 void **report = NULL;
9663 uint32_t bktCnt;
9664 uint32_t bktSize;
9665 uint32_t *clientCnt;
9666
9667 ASSERT_GATED();
9668
9669 report = NULL;
9670 if (channel_id == kAssertDelayChID) {
9671 report = &assertOnWakeReport;
9672 bktCnt = kAssertDelayBcktCnt;
9673 bktSize = kAssertDelayBcktSize;
9674 clientCnt = &assertOnWakeClientCnt;
9675 } else if (channel_id == kSleepDelaysChID) {
9676 report = &sleepDelaysReport;
9677 bktCnt = kSleepDelaysBcktCnt;
9678 bktSize = kSleepDelaysBcktSize;
9679 clientCnt = &sleepDelaysClientCnt;
9680 } else {
9681 assert(false);
9682 return;
9683 }
9684
9685 switch (action) {
9686 case kIOReportEnable:
9687
9688 if (*report) {
9689 (*clientCnt)++;
9690 break;
9691 }
9692
9693 reportSize = HISTREPORT_BUFSIZE(bktCnt);
9694 *report = IOMallocZeroData(reportSize);
9695 if (*report == NULL) {
9696 break;
9697 }
9698 HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9699 getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9700
9701 if (channel_id == kAssertDelayChID) {
9702 assertOnWakeSecs = 0;
9703 }
9704
9705 break;
9706
9707 case kIOReportDisable:
9708 if (*clientCnt == 0) {
9709 break;
9710 }
9711 if (*clientCnt == 1) {
9712 IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
9713 *report = NULL;
9714 }
9715 (*clientCnt)--;
9716
9717 if (channel_id == kAssertDelayChID) {
9718 assertOnWakeSecs = -1; // Invalid value to prevent updates
9719 }
9720 break;
9721
9722 case kIOReportGetDimensions:
9723 if (*report) {
9724 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9725 }
9726 break;
9727 }
9728
9729 return;
9730 }
9731
9732 IOReturn
9733 IOPMrootDomain::configureReport(IOReportChannelList *channelList,
9734 IOReportConfigureAction action,
9735 void *result,
9736 void *destination)
9737 {
9738 unsigned cnt;
9739 uint64_t configAction = (uint64_t)action;
9740
9741 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9742 if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
9743 (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
9744 (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
9745 if (action != kIOReportGetDimensions) {
9746 continue;
9747 }
9748 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
9749 } else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
9750 (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
9751 gIOPMWorkLoop->runAction(
9752 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
9753 (OSObject *)this, (void *)channelList->channels[cnt].channel_id,
9754 (void *)configAction, (void *)result);
9755 }
9756 }
9757
9758 return super::configureReport(channelList, action, result, destination);
9759 }
9760
9761 IOReturn
9762 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9763 {
9764 uint32_t size2cpy;
9765 void *data2cpy;
9766 void **report;
9767
9768 ASSERT_GATED();
9769
9770 report = NULL;
9771 if (ch_id == kAssertDelayChID) {
9772 report = &assertOnWakeReport;
9773 } else if (ch_id == kSleepDelaysChID) {
9774 report = &sleepDelaysReport;
9775 } else {
9776 assert(false);
9777 return kIOReturnBadArgument;
9778 }
9779
9780 if (*report == NULL) {
9781 return kIOReturnNotOpen;
9782 }
9783
9784 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9785 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9786 return kIOReturnOverrun;
9787 }
9788
9789 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9790 dest->appendBytes(data2cpy, size2cpy);
9791
9792 return kIOReturnSuccess;
9793 }
9794
9795 IOReturn
9796 IOPMrootDomain::updateReport(IOReportChannelList *channelList,
9797 IOReportUpdateAction action,
9798 void *result,
9799 void *destination)
9800 {
9801 uint32_t size2cpy;
9802 void *data2cpy;
9803 uint8_t buf[SIMPLEREPORT_BUFSIZE];
9804 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9805 unsigned cnt;
9806 uint64_t ch_id;
9807
9808 if (action != kIOReportCopyChannelData) {
9809 goto exit;
9810 }
9811
9812 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9813 ch_id = channelList->channels[cnt].channel_id;
9814
9815 if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
9816 gIOPMWorkLoop->runAction(
9817 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
9818 (OSObject *)this, (void *)ch_id,
9819 (void *)result, (void *)dest);
9820 continue;
9821 } else if ((ch_id == kSleepCntChID) ||
9822 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9823 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9824 } else {
9825 continue;
9826 }
9827
9828 if (ch_id == kSleepCntChID) {
9829 SIMPLEREPORT_SETVALUE(buf, sleepCnt);
9830 } else if (ch_id == kDarkWkCntChID) {
9831 SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
9832 } else if (ch_id == kUserWkCntChID) {
9833 SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
9834 }
9835
9836 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9837 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9838 dest->appendBytes(data2cpy, size2cpy);
9839 }
9840
9841 exit:
9842 return super::updateReport(channelList, action, result, destination);
9843 }
9844
9845
9846 //******************************************************************************
9847 // PMTraceWorker Class
9848 //
9849 //******************************************************************************
9850
9851 #undef super
9852 #define super OSObject
9853 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9854
9855 #define kPMBestGuessPCIDevicesCount 25
9856 #define kPMMaxRTCBitfieldSize 32
9857
9858 OSPtr<PMTraceWorker>
9859 PMTraceWorker::tracer(IOPMrootDomain * owner)
9860 {
9861 OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9862 if (!me || !me->init()) {
9863 return NULL;
9864 }
9865
9866 DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9867
9868 // Note that we cannot instantiate the PCI device -> bit mappings here, since
9869 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
9870 // this dictionary lazily.
9871 me->owner = owner;
9872 me->pciDeviceBitMappings = NULL;
9873 me->pmTraceWorkerLock = IOLockAlloc();
9874 me->tracePhase = kIOPMTracePointSystemUp;
9875 me->traceData32 = 0;
9876 me->loginWindowData = 0;
9877 me->coreDisplayData = 0;
9878 me->coreGraphicsData = 0;
9879 return me;
9880 }
9881
9882 void
9883 PMTraceWorker::RTC_TRACE(void)
9884 {
9885 if (tracePointHandler && tracePointTarget) {
9886 uint32_t wordA;
9887
9888 IOLockLock(pmTraceWorkerLock);
9889 wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9890 (coreGraphicsData << 8) | tracePhase;
9891 IOLockUnlock(pmTraceWorkerLock);
9892
9893 tracePointHandler( tracePointTarget, traceData32, wordA );
9894 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
9895 }
9896 #if DEVELOPMENT || DEBUG
9897 if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
9898 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
9899 IOLock *l = IOLockAlloc();
9900 IOLockLock(l);
9901 IOLockLock(l);
9902 }
9903 #endif /* DEVELOPMENT || DEBUG */
9904 }
9905
9906 int
9907 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
9908 {
9909 OSSharedPtr<const OSSymbol> deviceName;
9910 int index = -1;
9911
9912 IOLockLock(pmTraceWorkerLock);
9913
9914 if (!pciDeviceBitMappings) {
9915 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
9916 if (!pciDeviceBitMappings) {
9917 goto exit;
9918 }
9919 }
9920
9921 // Check for bitmask overflow.
9922 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
9923 goto exit;
9924 }
9925
9926 if ((deviceName = pciDevice->copyName()) &&
9927 (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
9928 pciDeviceBitMappings->setObject(deviceName.get())) {
9929 index = pciDeviceBitMappings->getCount() - 1;
9930 _LOG("PMTrace PCI array: set object %s => %d\n",
9931 deviceName->getCStringNoCopy(), index);
9932 }
9933
9934 if (!addedToRegistry && (index >= 0)) {
9935 addedToRegistry = owner->setProperty("PCITopLevel", this);
9936 }
9937
9938 exit:
9939 IOLockUnlock(pmTraceWorkerLock);
9940 return index;
9941 }
9942
9943 bool
9944 PMTraceWorker::serialize(OSSerialize *s) const
9945 {
9946 bool ok = false;
9947 if (pciDeviceBitMappings) {
9948 IOLockLock(pmTraceWorkerLock);
9949 ok = pciDeviceBitMappings->serialize(s);
9950 IOLockUnlock(pmTraceWorkerLock);
9951 }
9952 return ok;
9953 }
9954
9955 void
9956 PMTraceWorker::tracePoint(uint8_t phase)
9957 {
9958 // clear trace detail when phase begins
9959 if (tracePhase != phase) {
9960 traceData32 = 0;
9961 }
9962
9963 tracePhase = phase;
9964
9965 DLOG("trace point 0x%02x\n", tracePhase);
9966 RTC_TRACE();
9967 }
9968
9969 void
9970 PMTraceWorker::traceDetail(uint32_t detail)
9971 {
9972 if (detail == traceData32) {
9973 return;
9974 }
9975 traceData32 = detail;
9976 RTC_TRACE();
9977 }
9978
9979 void
9980 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
9981 {
9982 switch (component) {
9983 case kIOPMLoginWindowProgress:
9984 loginWindowData = data & kIOPMLoginWindowProgressMask;
9985 break;
9986 case kIOPMCoreDisplayProgress:
9987 coreDisplayData = data & kIOPMCoreDisplayProgressMask;
9988 break;
9989 case kIOPMCoreGraphicsProgress:
9990 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
9991 break;
9992 default:
9993 return;
9994 }
9995
9996 DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
9997 RTC_TRACE();
9998 }
9999
10000 void
10001 PMTraceWorker::tracePCIPowerChange(
10002 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
10003 {
10004 uint32_t bitMask;
10005 uint32_t expectedFlag;
10006
10007 // Ignore PCI changes outside of system sleep/wake.
10008 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
10009 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
10010 return;
10011 }
10012
10013 // Only record the WillChange transition when going to sleep,
10014 // and the DidChange on the way up.
10015 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
10016 expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
10017 kIOPMDomainWillChange : kIOPMDomainDidChange;
10018 if (changeFlags != expectedFlag) {
10019 return;
10020 }
10021
10022 // Mark this device off in our bitfield
10023 if (bitNum < kPMMaxRTCBitfieldSize) {
10024 bitMask = (1 << bitNum);
10025
10026 if (kPowerChangeStart == type) {
10027 traceData32 |= bitMask;
10028 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
10029 service->getName(), bitNum, bitMask, traceData32);
10030 owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10031 } else {
10032 traceData32 &= ~bitMask;
10033 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10034 service->getName(), bitNum, bitMask, traceData32);
10035 owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10036 }
10037
10038 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10039 RTC_TRACE();
10040 }
10041 }
10042
10043 uint64_t
10044 PMTraceWorker::getPMStatusCode()
10045 {
10046 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10047 }
10048
10049 uint8_t
10050 PMTraceWorker::getTracePhase()
10051 {
10052 return tracePhase;
10053 }
10054
10055 uint32_t
10056 PMTraceWorker::getTraceData()
10057 {
10058 return traceData32;
10059 }
10060
10061 // MARK: -
10062 // MARK: PMHaltWorker
10063
10064 //******************************************************************************
10065 // PMHaltWorker Class
10066 //
10067 //******************************************************************************
10068
10069 PMHaltWorker *
10070 PMHaltWorker::worker( void )
10071 {
10072 PMHaltWorker * me;
10073 IOThread thread;
10074
10075 do {
10076 me = OSTypeAlloc( PMHaltWorker );
10077 if (!me || !me->init()) {
10078 break;
10079 }
10080
10081 me->lock = IOLockAlloc();
10082 if (!me->lock) {
10083 break;
10084 }
10085
10086 DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10087 me->retain(); // thread holds extra retain
10088 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10089 me->release();
10090 break;
10091 }
10092 thread_deallocate(thread);
10093 return me;
10094 } while (false);
10095
10096 if (me) {
10097 me->release();
10098 }
10099 return NULL;
10100 }
10101
10102 void
10103 PMHaltWorker::free( void )
10104 {
10105 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10106 if (lock) {
10107 IOLockFree(lock);
10108 lock = NULL;
10109 }
10110 return OSObject::free();
10111 }
10112
10113 void
10114 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10115 {
10116 PMHaltWorker * me = (PMHaltWorker *) arg;
10117
10118 IOLockLock( gPMHaltLock );
10119 gPMHaltBusyCount++;
10120 me->depth = gPMHaltDepth;
10121 IOLockUnlock( gPMHaltLock );
10122
10123 while (me->depth >= 0) {
10124 PMHaltWorker::work( me );
10125
10126 IOLockLock( gPMHaltLock );
10127 if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10128 // This is the last thread to finish work on this level,
10129 // inform everyone to start working on next lower level.
10130 gPMHaltDepth--;
10131 me->depth = gPMHaltDepth;
10132 gPMHaltIdleCount = 0;
10133 thread_wakeup((event_t) &gPMHaltIdleCount);
10134 } else {
10135 // One or more threads are still working on this level,
10136 // this thread must wait.
10137 me->depth = gPMHaltDepth - 1;
10138 do {
10139 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10140 } while (me->depth != gPMHaltDepth);
10141 }
10142 IOLockUnlock( gPMHaltLock );
10143 }
10144
10145 // No more work to do, terminate thread
10146 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10147 thread_wakeup( &gPMHaltDepth );
10148 me->release();
10149 }
10150
10151 void
10152 PMHaltWorker::work( PMHaltWorker * me )
10153 {
10154 OSSharedPtr<IOService> service;
10155 OSSet * inner;
10156 AbsoluteTime startTime, elapsedTime;
10157 UInt32 deltaTime;
10158 bool timeout;
10159
10160 while (true) {
10161 timeout = false;
10162
10163 // Claim an unit of work from the shared pool
10164 IOLockLock( gPMHaltLock );
10165 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10166 if (inner) {
10167 service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10168 if (service) {
10169 inner->removeObject(service.get());
10170 }
10171 }
10172 IOLockUnlock( gPMHaltLock );
10173 if (!service) {
10174 break; // no more work at this depth
10175 }
10176 clock_get_uptime(&startTime);
10177
10178 if (!service->isInactive() &&
10179 service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10180 IOLockLock(me->lock);
10181 me->startTime = startTime;
10182 me->service = service.get();
10183 me->timeout = false;
10184 IOLockUnlock(me->lock);
10185
10186 service->systemWillShutdown( gPMHaltMessageType);
10187
10188 // Wait for driver acknowledgement
10189 IOLockLock(me->lock);
10190 while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10191 IOLockSleep(me->lock, me, THREAD_UNINT);
10192 }
10193 me->service = NULL;
10194 timeout = me->timeout;
10195 IOLockUnlock(me->lock);
10196 }
10197
10198 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10199 if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10200 LOG("%s driver %s (0x%llx) took %u ms\n",
10201 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10202 "PowerOff" : "Restart",
10203 service->getName(), service->getRegistryEntryID(),
10204 (uint32_t) deltaTime );
10205 halt_log_enter("PowerOff/Restart handler completed",
10206 OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10207 elapsedTime);
10208 }
10209
10210 me->visits++;
10211 }
10212 }
10213
10214 void
10215 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10216 {
10217 UInt64 nano;
10218 AbsoluteTime startTime;
10219 AbsoluteTime endTime;
10220
10221 endTime = *now;
10222
10223 IOLockLock(me->lock);
10224 if (me->service && !me->timeout) {
10225 startTime = me->startTime;
10226 nano = 0;
10227 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10228 SUB_ABSOLUTETIME(&endTime, &startTime);
10229 absolutetime_to_nanoseconds(endTime, &nano);
10230 }
10231 if (nano > 3000000000ULL) {
10232 me->timeout = true;
10233
10234 halt_log_enter("PowerOff/Restart still waiting on handler",
10235 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10236 endTime);
10237 MSG("%s still waiting on %s\n",
10238 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart",
10239 me->service->getName());
10240 }
10241 }
10242 IOLockUnlock(me->lock);
10243 }
10244
10245 //******************************************************************************
10246 // acknowledgeSystemWillShutdown
10247 //
10248 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10249 //******************************************************************************
10250
10251 void
10252 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10253 {
10254 PMHaltWorker * worker;
10255 OSSharedPtr<OSObject> prop;
10256
10257 if (!from) {
10258 return;
10259 }
10260
10261 //DLOG("%s acknowledged\n", from->getName());
10262 prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10263 if (prop) {
10264 worker = (PMHaltWorker *) prop.get();
10265 IOLockLock(worker->lock);
10266 from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10267 thread_wakeup((event_t) worker);
10268 IOLockUnlock(worker->lock);
10269 } else {
10270 DLOG("%s acknowledged without worker property\n",
10271 from->getName());
10272 }
10273 }
10274
10275
10276 //******************************************************************************
10277 // notifySystemShutdown
10278 //
10279 // Notify all objects in PM tree that system will shutdown or restart
10280 //******************************************************************************
10281
10282 static void
10283 notifySystemShutdown( IOService * root, uint32_t messageType )
10284 {
10285 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10286 OSSharedPtr<IORegistryIterator> iter;
10287 IORegistryEntry * entry;
10288 IOService * node;
10289 OSSet * inner;
10290 OSSharedPtr<OSSet> newInner;
10291 PMHaltWorker * workers[kPMHaltMaxWorkers];
10292 AbsoluteTime deadline;
10293 unsigned int totalNodes = 0;
10294 unsigned int depth;
10295 unsigned int rootDepth;
10296 unsigned int numWorkers;
10297 unsigned int count;
10298 int waitResult;
10299 void * baseFunc;
10300 bool ok;
10301
10302 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10303
10304 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10305
10306 // Iterate the entire PM tree starting from root
10307
10308 rootDepth = root->getDepth( gIOPowerPlane );
10309 if (!rootDepth) {
10310 goto done;
10311 }
10312
10313 // debug - for repeated test runs
10314 while (PMHaltWorker::metaClass->getInstanceCount()) {
10315 IOSleep(1);
10316 }
10317
10318 if (!gPMHaltArray) {
10319 gPMHaltArray = OSArray::withCapacity(40);
10320 if (!gPMHaltArray) {
10321 goto done;
10322 }
10323 } else { // debug
10324 gPMHaltArray->flushCollection();
10325 }
10326
10327 if (!gPMHaltLock) {
10328 gPMHaltLock = IOLockAlloc();
10329 if (!gPMHaltLock) {
10330 goto done;
10331 }
10332 }
10333
10334 if (!gPMHaltClientAcknowledgeKey) {
10335 gPMHaltClientAcknowledgeKey =
10336 OSSymbol::withCStringNoCopy("PMShutdown");
10337 if (!gPMHaltClientAcknowledgeKey) {
10338 goto done;
10339 }
10340 }
10341
10342 gPMHaltMessageType = messageType;
10343
10344 // Depth-first walk of PM plane
10345
10346 iter = IORegistryIterator::iterateOver(
10347 root, gIOPowerPlane, kIORegistryIterateRecursively);
10348
10349 if (iter) {
10350 while ((entry = iter->getNextObject())) {
10351 node = OSDynamicCast(IOService, entry);
10352 if (!node) {
10353 continue;
10354 }
10355
10356 if (baseFunc ==
10357 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10358 continue;
10359 }
10360
10361 depth = node->getDepth( gIOPowerPlane );
10362 if (depth <= rootDepth) {
10363 continue;
10364 }
10365
10366 ok = false;
10367
10368 // adjust to zero based depth
10369 depth -= (rootDepth + 1);
10370
10371 // gPMHaltArray is an array of containers, each container
10372 // refers to nodes with the same depth.
10373
10374 count = gPMHaltArray->getCount();
10375 while (depth >= count) {
10376 // expand array and insert placeholders
10377 gPMHaltArray->setObject(PLACEHOLDER);
10378 count++;
10379 }
10380 count = gPMHaltArray->getCount();
10381 if (depth < count) {
10382 inner = (OSSet *)gPMHaltArray->getObject(depth);
10383 if (inner == PLACEHOLDER) {
10384 newInner = OSSet::withCapacity(40);
10385 if (newInner) {
10386 gPMHaltArray->replaceObject(depth, newInner.get());
10387 inner = newInner.get();
10388 }
10389 }
10390
10391 // PM nodes that appear more than once in the tree will have
10392 // the same depth, OSSet will refuse to add the node twice.
10393 if (inner) {
10394 ok = inner->setObject(node);
10395 }
10396 }
10397 if (!ok) {
10398 DLOG("Skipped PM node %s\n", node->getName());
10399 }
10400 }
10401 }
10402
10403 // debug only
10404 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10405 count = 0;
10406 if (inner != PLACEHOLDER) {
10407 count = inner->getCount();
10408 }
10409 DLOG("Nodes at depth %u = %u\n", i, count);
10410 }
10411
10412 // strip placeholders (not all depths are populated)
10413 numWorkers = 0;
10414 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10415 if (inner == PLACEHOLDER) {
10416 gPMHaltArray->removeObject(i);
10417 continue;
10418 }
10419 count = inner->getCount();
10420 if (count > numWorkers) {
10421 numWorkers = count;
10422 }
10423 totalNodes += count;
10424 i++;
10425 }
10426
10427 if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10428 goto done;
10429 }
10430
10431 gPMHaltBusyCount = 0;
10432 gPMHaltIdleCount = 0;
10433 gPMHaltDepth = gPMHaltArray->getCount() - 1;
10434
10435 // Create multiple workers (and threads)
10436
10437 if (numWorkers > kPMHaltMaxWorkers) {
10438 numWorkers = kPMHaltMaxWorkers;
10439 }
10440
10441 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10442 totalNodes, gPMHaltArray->getCount(), numWorkers);
10443
10444 for (unsigned int i = 0; i < numWorkers; i++) {
10445 workers[i] = PMHaltWorker::worker();
10446 }
10447
10448 // Wait for workers to exhaust all available work
10449
10450 IOLockLock(gPMHaltLock);
10451 while (gPMHaltDepth >= 0) {
10452 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10453
10454 waitResult = IOLockSleepDeadline(
10455 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10456 if (THREAD_TIMED_OUT == waitResult) {
10457 AbsoluteTime now;
10458 clock_get_uptime(&now);
10459
10460 IOLockUnlock(gPMHaltLock);
10461 for (unsigned int i = 0; i < numWorkers; i++) {
10462 if (workers[i]) {
10463 PMHaltWorker::checkTimeout(workers[i], &now);
10464 }
10465 }
10466 IOLockLock(gPMHaltLock);
10467 }
10468 }
10469 IOLockUnlock(gPMHaltLock);
10470
10471 // Release all workers
10472
10473 for (unsigned int i = 0; i < numWorkers; i++) {
10474 if (workers[i]) {
10475 workers[i]->release();
10476 }
10477 // worker also retained by it's own thread
10478 }
10479
10480 done:
10481 DLOG("%s done\n", __FUNCTION__);
10482 return;
10483 }
10484
10485 // MARK: -
10486 // MARK: Kernel Assertion
10487
10488 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10489
10490 IOPMDriverAssertionID
10491 IOPMrootDomain::createPMAssertion(
10492 IOPMDriverAssertionType whichAssertionBits,
10493 IOPMDriverAssertionLevel assertionLevel,
10494 IOService *ownerService,
10495 const char *ownerDescription)
10496 {
10497 IOReturn ret;
10498 IOPMDriverAssertionID newAssertion;
10499
10500 if (!pmAssertions) {
10501 return 0;
10502 }
10503
10504 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10505
10506 if (kIOReturnSuccess == ret) {
10507 #if (DEVELOPMENT || DEBUG)
10508 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10509 OSReportWithBacktrace("PMRD: createPMAssertion(0x%qx) %s (%s)", newAssertion, ownerService->getName(), ownerDescription);
10510 }
10511 #endif /* (DEVELOPMENT || DEBUG) */
10512 return newAssertion;
10513 } else {
10514 return 0;
10515 }
10516 }
10517
10518 IOReturn
10519 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10520 {
10521 #if (DEVELOPMENT || DEBUG)
10522 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10523 PMAssertStruct *details = pmAssertions->detailsForID(releaseAssertion, NULL);
10524 if (details && details->ownerService && details->ownerString) {
10525 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx) %s (%s)", releaseAssertion,
10526 details->ownerService->getName(), details->ownerString->getCStringNoCopy());
10527 } else {
10528 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx)", releaseAssertion);
10529 }
10530 }
10531 #endif /* (DEVELOPMENT || DEBUG) */
10532 if (!pmAssertions) {
10533 return kIOReturnInternalError;
10534 }
10535 return pmAssertions->releaseAssertion(releaseAssertion);
10536 }
10537
10538
10539 IOReturn
10540 IOPMrootDomain::setPMAssertionLevel(
10541 IOPMDriverAssertionID assertionID,
10542 IOPMDriverAssertionLevel assertionLevel)
10543 {
10544 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10545 }
10546
10547 IOPMDriverAssertionLevel
10548 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10549 {
10550 IOPMDriverAssertionType sysLevels;
10551
10552 if (!pmAssertions || whichAssertion == 0) {
10553 return kIOPMDriverAssertionLevelOff;
10554 }
10555
10556 sysLevels = pmAssertions->getActivatedAssertions();
10557
10558 // Check that every bit set in argument 'whichAssertion' is asserted
10559 // in the aggregate bits.
10560 if ((sysLevels & whichAssertion) == whichAssertion) {
10561 return kIOPMDriverAssertionLevelOn;
10562 } else {
10563 return kIOPMDriverAssertionLevelOff;
10564 }
10565 }
10566
10567 IOReturn
10568 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10569 {
10570 if (!pmAssertions) {
10571 return kIOReturnNotFound;
10572 }
10573
10574 return pmAssertions->setUserAssertionLevels(inLevels);
10575 }
10576
10577 IOReturn
10578 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10579 {
10580 return gIOPMWorkLoop->runActionBlock(^{
10581 if (_driverKitMatchingAssertionCount != 0) {
10582 _driverKitMatchingAssertionCount++;
10583 return kIOReturnSuccess;
10584 } else {
10585 if (kSystemTransitionSleep == _systemTransitionType) {
10586 // system going to sleep
10587 return kIOReturnBusy;
10588 } else {
10589 // createPMAssertion is asynchronous.
10590 // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10591 // The assertion is used so that on release, we reevaluate all assertions
10592 _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10593 if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10594 _driverKitMatchingAssertionCount = 1;
10595 return kIOReturnSuccess;
10596 } else {
10597 return kIOReturnBusy;
10598 }
10599 }
10600 }
10601 });
10602 }
10603
10604 void
10605 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10606 {
10607 gIOPMWorkLoop->runActionBlock(^{
10608 if (_driverKitMatchingAssertionCount != 0) {
10609 _driverKitMatchingAssertionCount--;
10610 if (_driverKitMatchingAssertionCount == 0) {
10611 releasePMAssertion(_driverKitMatchingAssertion);
10612 _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10613 }
10614 } else {
10615 panic("Over-release of driverkit matching assertion");
10616 }
10617 return kIOReturnSuccess;
10618 });
10619 }
10620
10621 bool
10622 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10623 {
10624 if (pmAssertions) {
10625 pmAssertions->publishProperties();
10626 }
10627 return IOService::serializeProperties(s);
10628 }
10629
10630 OSSharedPtr<OSObject>
10631 IOPMrootDomain::copyProperty( const char * aKey) const
10632 {
10633 OSSharedPtr<OSObject> obj;
10634 obj = IOService::copyProperty(aKey);
10635
10636 if (obj) {
10637 return obj;
10638 }
10639
10640 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10641 sizeof(kIOPMSleepWakeWdogRebootKey))) {
10642 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10643 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10644 } else {
10645 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10646 }
10647 }
10648
10649 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10650 sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10651 if (swd_flags & SWD_VALID_LOGS) {
10652 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10653 } else {
10654 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10655 }
10656 }
10657
10658 /*
10659 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
10660 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10661 * issued by DisplayWrangler on darkwake.
10662 */
10663 if (!strcmp(aKey, "DesktopMode")) {
10664 if (desktopMode) {
10665 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10666 } else {
10667 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10668 }
10669 }
10670 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10671 if (displayIdleForDemandSleep) {
10672 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10673 } else {
10674 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10675 }
10676 }
10677
10678 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10679 OSSharedPtr<OSArray> array;
10680 WAKEEVENT_LOCK();
10681 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10682 OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10683 if (collection) {
10684 array = OSDynamicPtrCast<OSArray>(collection);
10685 }
10686 }
10687 WAKEEVENT_UNLOCK();
10688 return os::move(array);
10689 }
10690
10691 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10692 OSSharedPtr<OSArray> array;
10693 IOLockLock(pmStatsLock);
10694 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10695 OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10696 if (collection) {
10697 array = OSDynamicPtrCast<OSArray>(collection);
10698 }
10699 }
10700 IOLockUnlock(pmStatsLock);
10701 return os::move(array);
10702 }
10703
10704 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10705 OSArray *idleSleepList = NULL;
10706 gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10707 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10708 }
10709
10710 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10711 OSArray *systemSleepList = NULL;
10712 gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10713 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10714 }
10715
10716 if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10717 OSArray *idleSleepList = NULL;
10718 gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10719 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10720 }
10721
10722 if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10723 OSArray *systemSleepList = NULL;
10724 gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10725 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10726 }
10727 return NULL;
10728 }
10729
10730 // MARK: -
10731 // MARK: Wake Event Reporting
10732
10733 void
10734 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10735 {
10736 WAKEEVENT_LOCK();
10737 strlcpy(outBuf, gWakeReasonString, bufSize);
10738 WAKEEVENT_UNLOCK();
10739 }
10740
10741 void
10742 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10743 {
10744 WAKEEVENT_LOCK();
10745 strlcpy(outBuf, gShutdownReasonString, bufSize);
10746 WAKEEVENT_UNLOCK();
10747 }
10748
10749 //******************************************************************************
10750 // acceptSystemWakeEvents
10751 //
10752 // Private control for the acceptance of driver wake event claims.
10753 //******************************************************************************
10754
10755 void
10756 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10757 {
10758 bool logWakeReason = false;
10759
10760 WAKEEVENT_LOCK();
10761 switch (control) {
10762 case kAcceptSystemWakeEvents_Enable:
10763 assert(_acceptSystemWakeEvents == false);
10764 if (!_systemWakeEventsArray) {
10765 _systemWakeEventsArray = OSArray::withCapacity(4);
10766 }
10767 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10768 if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10769 gWakeReasonString[0] = '\0';
10770 if (_systemWakeEventsArray) {
10771 _systemWakeEventsArray->flushCollection();
10772 }
10773 }
10774
10775 // Remove stale WakeType property before system sleep
10776 removeProperty(kIOPMRootDomainWakeTypeKey);
10777 removeProperty(kIOPMRootDomainWakeReasonKey);
10778 break;
10779
10780 case kAcceptSystemWakeEvents_Disable:
10781 _acceptSystemWakeEvents = false;
10782 #if defined(XNU_TARGET_OS_OSX)
10783 logWakeReason = (gWakeReasonString[0] != '\0');
10784 #else /* !defined(XNU_TARGET_OS_OSX) */
10785 logWakeReason = gWakeReasonSysctlRegistered;
10786 #if DEVELOPMENT
10787 static int panic_allowed = -1;
10788
10789 if ((panic_allowed == -1) &&
10790 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10791 panic_allowed = 0;
10792 }
10793
10794 if (panic_allowed) {
10795 size_t i = 0;
10796 // Panic if wake reason is null or empty
10797 for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10798 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10799 break;
10800 }
10801 }
10802 if (i >= strlen(gWakeReasonString)) {
10803 panic("Wake reason is empty");
10804 }
10805 }
10806 #endif /* DEVELOPMENT */
10807 #endif /* !defined(XNU_TARGET_OS_OSX) */
10808
10809 // publish kIOPMRootDomainWakeReasonKey if not already set
10810 if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10811 setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10812 }
10813 break;
10814
10815 case kAcceptSystemWakeEvents_Reenable:
10816 assert(_acceptSystemWakeEvents == false);
10817 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10818 removeProperty(kIOPMRootDomainWakeReasonKey);
10819 break;
10820 }
10821 WAKEEVENT_UNLOCK();
10822
10823 if (logWakeReason) {
10824 MSG("system wake events: %s\n", gWakeReasonString);
10825 }
10826 }
10827
10828 //******************************************************************************
10829 // claimSystemWakeEvent
10830 //
10831 // For a driver to claim a device is the source/conduit of a system wake event.
10832 //******************************************************************************
10833
10834 void
10835 IOPMrootDomain::claimSystemWakeEvent(
10836 IOService * device,
10837 IOOptionBits flags,
10838 const char * reason,
10839 OSObject * details )
10840 {
10841 OSSharedPtr<const OSSymbol> deviceName;
10842 OSSharedPtr<OSNumber> deviceRegId;
10843 OSSharedPtr<OSNumber> claimTime;
10844 OSSharedPtr<OSData> flagsData;
10845 OSSharedPtr<OSString> reasonString;
10846 OSSharedPtr<OSDictionary> dict;
10847 uint64_t timestamp;
10848 bool addWakeReason;
10849
10850 if (!device || !reason) {
10851 return;
10852 }
10853
10854 pmEventTimeStamp(×tamp);
10855
10856 IOOptionBits aotFlags = 0;
10857 bool needAOTEvaluate = FALSE;
10858
10859 if (kIOPMAOTModeAddEventFlags & _aotMode) {
10860 if (!strcmp("hold", reason)
10861 || !strcmp("help", reason)
10862 || !strcmp("menu", reason)
10863 || !strcmp("stockholm", reason)
10864 || !strcmp("ringer", reason)
10865 || !strcmp("ringerab", reason)
10866 || !strcmp("smc0", reason)
10867 || !strcmp("AOP.RTPWakeupAP", reason)
10868 || !strcmp("AOP.RTP_AP_IRQ", reason)
10869 || !strcmp("BT.OutboxNotEmpty", reason)
10870 || !strcmp("WL.OutboxNotEmpty", reason)) {
10871 flags |= kIOPMWakeEventAOTExit;
10872 }
10873 }
10874
10875 #if DEVELOPMENT || DEBUG
10876 if (_aotLingerTime && !strcmp("rtc", reason)) {
10877 flags |= kIOPMWakeEventAOTPossibleExit;
10878 }
10879 #endif /* DEVELOPMENT || DEBUG */
10880
10881 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10882 // Publishing the WakeType is serialized by the PM work loop
10883 if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
10884 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10885 (void *) _nextScheduledAlarmType.get());
10886 }
10887
10888 // Workaround for the missing wake HID event
10889 if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
10890 if (!strcmp("trackpadkeyboard", reason)) {
10891 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10892 (void *) gIOPMWakeTypeUserKey.get());
10893 }
10894 }
10895 #endif
10896
10897 deviceName = device->copyName(gIOServicePlane);
10898 deviceRegId = OSNumber::withNumber(device->getRegistryEntryID(), 64);
10899 claimTime = OSNumber::withNumber(timestamp, 64);
10900 flagsData = OSData::withValue(flags);
10901 reasonString = OSString::withCString(reason);
10902 dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
10903 if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
10904 goto done;
10905 }
10906
10907 dict->setObject(gIONameKey, deviceName.get());
10908 dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
10909 dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
10910 dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
10911 dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
10912 if (details) {
10913 dict->setObject(kIOPMWakeEventDetailsKey, details);
10914 }
10915
10916 WAKEEVENT_LOCK();
10917 addWakeReason = _acceptSystemWakeEvents;
10918 if (_aotMode) {
10919 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
10920 }
10921 aotFlags = (kIOPMWakeEventAOTFlags & flags);
10922 aotFlags = (aotFlags & ~_aotPendingFlags);
10923 needAOTEvaluate = false;
10924 if (_aotNow && aotFlags) {
10925 if (kIOPMWakeEventAOTPossibleExit & flags) {
10926 _aotMetrics->possibleCount++;
10927 }
10928 if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
10929 _aotMetrics->confirmedPossibleCount++;
10930 }
10931 if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
10932 _aotMetrics->rejectedPossibleCount++;
10933 }
10934 if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
10935 _aotMetrics->expiredPossibleCount++;
10936 }
10937
10938 _aotPendingFlags |= aotFlags;
10939 addWakeReason = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
10940 needAOTEvaluate = _aotReadyToFullWake;
10941 }
10942 DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
10943 reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
10944 _aotNow, pmTracer->getTracePhase(), addWakeReason);
10945
10946 #if DEVELOPMENT || DEBUG
10947 if (addWakeReason) {
10948 record_system_event(SYSTEM_EVENT_TYPE_INFO,
10949 SYSTEM_EVENT_SUBSYSTEM_PMRD,
10950 "Report System Wake Event",
10951 "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
10952 reason,
10953 (int)flags,
10954 deviceName->getCStringNoCopy(),
10955 device->getRegistryEntryID()
10956 );
10957 }
10958 #endif /* DEVELOPMENT || DEBUG */
10959
10960 if (!gWakeReasonSysctlRegistered) {
10961 // Lazy registration until the platform driver stops registering
10962 // the same name.
10963 gWakeReasonSysctlRegistered = true;
10964 }
10965 if (addWakeReason) {
10966 _systemWakeEventsArray->setObject(dict.get());
10967 if (gWakeReasonString[0] != '\0') {
10968 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
10969 }
10970 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
10971 }
10972
10973 WAKEEVENT_UNLOCK();
10974 if (needAOTEvaluate) {
10975 // Call aotEvaluate() on PM work loop since it may call
10976 // aotExit() which accesses PM state.
10977 pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
10978 }
10979
10980 done:
10981 return;
10982 }
10983
10984 //******************************************************************************
10985 // claimSystemBootEvent
10986 //
10987 // For a driver to claim a device is the source/conduit of a system boot event.
10988 //******************************************************************************
10989
10990 void
10991 IOPMrootDomain::claimSystemBootEvent(
10992 IOService * device,
10993 IOOptionBits flags,
10994 const char * reason,
10995 __unused OSObject * details )
10996 {
10997 if (!device || !reason) {
10998 return;
10999 }
11000
11001 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11002 #if DEVELOPMENT || DEBUG
11003 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11004 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11005 "Report System Boot Device",
11006 "Reason: %s Flags: 0x%x Device: %s",
11007 reason,
11008 (int)flags,
11009 device->getName()
11010 );
11011 #endif /* DEVELOPMENT || DEBUG */
11012 WAKEEVENT_LOCK();
11013 if (!gBootReasonSysctlRegistered) {
11014 // Lazy sysctl registration after setting gBootReasonString
11015 strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
11016 os_atomic_store(&gBootReasonSysctlRegistered, true, release);
11017 }
11018 WAKEEVENT_UNLOCK();
11019 }
11020
11021 //******************************************************************************
11022 // claimSystemShutdownEvent
11023 //
11024 // For drivers to claim a system shutdown event on the ensuing boot.
11025 //******************************************************************************
11026
11027 void
11028 IOPMrootDomain::claimSystemShutdownEvent(
11029 IOService * device,
11030 IOOptionBits flags,
11031 const char * reason,
11032 __unused OSObject * details )
11033 {
11034 if (!device || !reason) {
11035 return;
11036 }
11037
11038 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11039 #if DEVELOPMENT || DEBUG
11040 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11041 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11042 "Report System Shutdown Cause From Previous Boot",
11043 "Reason: %s Flags: 0x%x Device: %s",
11044 reason,
11045 (int)flags,
11046 device->getName()
11047 );
11048 #endif /* DEVELOPMENT || DEBUG */
11049 WAKEEVENT_LOCK();
11050 if (gShutdownReasonString[0] != '\0') {
11051 strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11052 }
11053 strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11054
11055 gShutdownReasonSysctlRegistered = true;
11056 WAKEEVENT_UNLOCK();
11057 }
11058
11059 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11060
11061 // MARK: -
11062 // MARK: PMSettingHandle
11063
11064 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11065
11066 void
11067 PMSettingHandle::free( void )
11068 {
11069 if (pmso) {
11070 pmso->clientHandleFreed();
11071 pmso->release();
11072 pmso = NULL;
11073 }
11074
11075 OSObject::free();
11076 }
11077
11078 // MARK: -
11079 // MARK: PMSettingObject
11080
11081 #undef super
11082 #define super OSObject
11083 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11084
11085 /*
11086 * Static constructor/initializer for PMSettingObject
11087 */
11088 PMSettingObject *PMSettingObject::pmSettingObject(
11089 IOPMrootDomain * parent_arg,
11090 IOPMSettingControllerCallback handler_arg,
11091 OSObject * target_arg,
11092 uintptr_t refcon_arg,
11093 uint32_t supportedPowerSources,
11094 const OSSymbol * settings[],
11095 OSObject * *handle_obj)
11096 {
11097 uint32_t settingCount = 0;
11098 PMSettingObject *pmso = NULL;
11099 PMSettingHandle *pmsh = NULL;
11100
11101 if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11102 return NULL;
11103 }
11104
11105 // count OSSymbol entries in NULL terminated settings array
11106 while (settings[settingCount]) {
11107 settingCount++;
11108 }
11109 if (0 == settingCount) {
11110 return NULL;
11111 }
11112
11113 pmso = new PMSettingObject;
11114 if (!pmso || !pmso->init()) {
11115 goto fail;
11116 }
11117
11118 pmsh = new PMSettingHandle;
11119 if (!pmsh || !pmsh->init()) {
11120 goto fail;
11121 }
11122
11123 queue_init(&pmso->calloutQueue);
11124 pmso->parent = parent_arg;
11125 pmso->func = handler_arg;
11126 pmso->target = target_arg;
11127 pmso->refcon = refcon_arg;
11128 pmso->settingCount = settingCount;
11129
11130 pmso->retain(); // handle holds a retain on pmso
11131 pmsh->pmso = pmso;
11132 pmso->pmsh = pmsh;
11133
11134 pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11135 if (pmso->publishedFeatureID) {
11136 for (unsigned int i = 0; i < settingCount; i++) {
11137 // Since there is now at least one listener to this setting, publish
11138 // PM root domain support for it.
11139 parent_arg->publishPMSetting( settings[i],
11140 supportedPowerSources, &pmso->publishedFeatureID[i] );
11141 }
11142 }
11143
11144 *handle_obj = pmsh;
11145 return pmso;
11146
11147 fail:
11148 if (pmso) {
11149 pmso->release();
11150 }
11151 if (pmsh) {
11152 pmsh->release();
11153 }
11154 return NULL;
11155 }
11156
11157 void
11158 PMSettingObject::free( void )
11159 {
11160 if (publishedFeatureID) {
11161 for (const auto& featureID : publishedFeatureID) {
11162 if (featureID) {
11163 parent->removePublishedFeature( featureID );
11164 }
11165 }
11166
11167 publishedFeatureID = {};
11168 }
11169
11170 super::free();
11171 }
11172
11173 IOReturn
11174 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11175 {
11176 return (*func)(target, type, object, refcon);
11177 }
11178
11179 void
11180 PMSettingObject::clientHandleFreed( void )
11181 {
11182 parent->deregisterPMSettingObject(this);
11183 }
11184
11185 // MARK: -
11186 // MARK: PMAssertionsTracker
11187
11188 //*********************************************************************************
11189 //*********************************************************************************
11190 //*********************************************************************************
11191 // class PMAssertionsTracker Implementation
11192
11193 #define kAssertUniqueIDStart 500
11194
11195 PMAssertionsTracker *
11196 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11197 {
11198 PMAssertionsTracker *me;
11199
11200 me = new PMAssertionsTracker;
11201 if (!me || !me->init()) {
11202 if (me) {
11203 me->release();
11204 }
11205 return NULL;
11206 }
11207
11208 me->owner = rootDomain;
11209 me->issuingUniqueID = kAssertUniqueIDStart;
11210 me->assertionsArray = OSArray::withCapacity(5);
11211 me->assertionsKernel = 0;
11212 me->assertionsUser = 0;
11213 me->assertionsCombined = 0;
11214 me->assertionsArrayLock = IOLockAlloc();
11215 me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11216
11217 assert(me->assertionsArray);
11218 assert(me->assertionsArrayLock);
11219
11220 return me;
11221 }
11222
11223 /* tabulate
11224 * - Update assertionsKernel to reflect the state of all
11225 * assertions in the kernel.
11226 * - Update assertionsCombined to reflect both kernel & user space.
11227 */
11228 void
11229 PMAssertionsTracker::tabulate(void)
11230 {
11231 int i;
11232 int count;
11233 const PMAssertStruct *_a = nullptr;
11234 OSValueObject<PMAssertStruct> *_d = nullptr;
11235
11236 IOPMDriverAssertionType oldKernel = assertionsKernel;
11237 IOPMDriverAssertionType oldCombined = assertionsCombined;
11238
11239 ASSERT_GATED();
11240
11241 assertionsKernel = 0;
11242 assertionsCombined = 0;
11243
11244 if (!assertionsArray) {
11245 return;
11246 }
11247
11248 if ((count = assertionsArray->getCount())) {
11249 for (i = 0; i < count; i++) {
11250 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11251 if (_d) {
11252 _a = _d->getBytesNoCopy();
11253 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11254 assertionsKernel |= _a->assertionBits;
11255 }
11256 }
11257 }
11258 }
11259
11260 tabulateProducerCount++;
11261 assertionsCombined = assertionsKernel | assertionsUser;
11262
11263 if ((assertionsKernel != oldKernel) ||
11264 (assertionsCombined != oldCombined)) {
11265 owner->evaluateAssertions(assertionsCombined, oldCombined);
11266 }
11267 }
11268
11269 void
11270 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11271 {
11272 AbsoluteTime now;
11273 uint64_t nsec;
11274
11275 if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11276 (assertStruct->assertCPUStartTime == 0)) {
11277 return;
11278 }
11279
11280 now = mach_absolute_time();
11281 SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11282 absolutetime_to_nanoseconds(now, &nsec);
11283 assertStruct->assertCPUDuration += nsec;
11284 assertStruct->assertCPUStartTime = 0;
11285
11286 if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11287 maxAssertCPUDuration = assertStruct->assertCPUDuration;
11288 maxAssertCPUEntryId = assertStruct->registryEntryID;
11289 }
11290 }
11291
11292 void
11293 PMAssertionsTracker::reportCPUBitAccounting( void )
11294 {
11295 const PMAssertStruct *_a = nullptr;
11296 OSValueObject<PMAssertStruct> *_d = nullptr;
11297 int i, count;
11298 AbsoluteTime now;
11299 uint64_t nsec;
11300
11301 ASSERT_GATED();
11302
11303 // Account for drivers that are still holding the CPU assertion
11304 if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11305 now = mach_absolute_time();
11306 if ((count = assertionsArray->getCount())) {
11307 for (i = 0; i < count; i++) {
11308 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11309 if (_d) {
11310 _a = _d->getBytesNoCopy();
11311 if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11312 (_a->level == kIOPMDriverAssertionLevelOn) &&
11313 (_a->assertCPUStartTime != 0)) {
11314 // Don't modify PMAssertStruct, leave that
11315 // for updateCPUBitAccounting()
11316 SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11317 absolutetime_to_nanoseconds(now, &nsec);
11318 nsec += _a->assertCPUDuration;
11319 if (nsec > maxAssertCPUDuration) {
11320 maxAssertCPUDuration = nsec;
11321 maxAssertCPUEntryId = _a->registryEntryID;
11322 }
11323 }
11324 }
11325 }
11326 }
11327 }
11328
11329 if (maxAssertCPUDuration) {
11330 DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11331 (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11332 }
11333
11334 maxAssertCPUDuration = 0;
11335 maxAssertCPUEntryId = 0;
11336 }
11337
11338 void
11339 PMAssertionsTracker::publishProperties( void )
11340 {
11341 OSSharedPtr<OSArray> assertionsSummary;
11342
11343 if (tabulateConsumerCount != tabulateProducerCount) {
11344 IOLockLock(assertionsArrayLock);
11345
11346 tabulateConsumerCount = tabulateProducerCount;
11347
11348 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11349 */
11350 assertionsSummary = copyAssertionsArray();
11351 if (assertionsSummary) {
11352 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11353 } else {
11354 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11355 }
11356
11357 /* Publish the IOPMrootDomain property "DriverPMAssertions"
11358 */
11359 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11360
11361 IOLockUnlock(assertionsArrayLock);
11362 }
11363 }
11364
11365 PMAssertStruct *
11366 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11367 {
11368 PMAssertStruct *_a = NULL;
11369 OSValueObject<PMAssertStruct> *_d = nullptr;
11370 int found = -1;
11371 int count = 0;
11372 int i = 0;
11373
11374 if (assertionsArray
11375 && (count = assertionsArray->getCount())) {
11376 for (i = 0; i < count; i++) {
11377 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11378 if (_d) {
11379 _a = _d->getMutableBytesNoCopy();
11380 if (_a && (_id == _a->id)) {
11381 found = i;
11382 break;
11383 }
11384 }
11385 }
11386 }
11387
11388 if (-1 == found) {
11389 return NULL;
11390 } else {
11391 if (index) {
11392 *index = found;
11393 }
11394 return _a;
11395 }
11396 }
11397
11398 /* PMAssertionsTracker::handleCreateAssertion
11399 * Perform assertion work on the PM workloop. Do not call directly.
11400 */
11401 IOReturn
11402 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11403 {
11404 PMAssertStruct *assertStruct = nullptr;
11405
11406 ASSERT_GATED();
11407
11408 if (newAssertion) {
11409 IOLockLock(assertionsArrayLock);
11410 assertStruct = newAssertion->getMutableBytesNoCopy();
11411 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11412 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11413 assertStruct->assertCPUStartTime = mach_absolute_time();
11414 }
11415 assertionsArray->setObject(newAssertion);
11416 IOLockUnlock(assertionsArrayLock);
11417 newAssertion->release();
11418
11419 tabulate();
11420 }
11421 return kIOReturnSuccess;
11422 }
11423
11424 /* PMAssertionsTracker::createAssertion
11425 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11426 * appropiate.
11427 */
11428 IOReturn
11429 PMAssertionsTracker::createAssertion(
11430 IOPMDriverAssertionType which,
11431 IOPMDriverAssertionLevel level,
11432 IOService *serviceID,
11433 const char *whoItIs,
11434 IOPMDriverAssertionID *outID)
11435 {
11436 OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11437 PMAssertStruct track;
11438
11439 // Warning: trillions and trillions of created assertions may overflow the unique ID.
11440 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11441 track.level = level;
11442 track.assertionBits = which;
11443
11444 // NB: ownerString is explicitly managed by PMAssertStruct
11445 // it will be released in `handleReleaseAssertion' below
11446 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11447 track.ownerService = serviceID;
11448 track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11449 track.modifiedTime = 0;
11450 pmEventTimeStamp(&track.createdTime);
11451 track.assertCPUStartTime = 0;
11452 track.assertCPUDuration = 0;
11453
11454 dataStore = OSValueObjectWithValue(track);
11455 if (!dataStore) {
11456 if (track.ownerString) {
11457 track.ownerString->release();
11458 track.ownerString = NULL;
11459 }
11460 return kIOReturnNoMemory;
11461 }
11462
11463 *outID = track.id;
11464
11465 if (owner && owner->pmPowerStateQueue) {
11466 // queue action is responsible for releasing dataStore
11467 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11468 }
11469
11470 return kIOReturnSuccess;
11471 }
11472
11473 /* PMAssertionsTracker::handleReleaseAssertion
11474 * Runs in PM workloop. Do not call directly.
11475 */
11476 IOReturn
11477 PMAssertionsTracker::handleReleaseAssertion(
11478 IOPMDriverAssertionID _id)
11479 {
11480 ASSERT_GATED();
11481
11482 int index;
11483 PMAssertStruct *assertStruct = detailsForID(_id, &index);
11484
11485 if (!assertStruct) {
11486 return kIOReturnNotFound;
11487 }
11488
11489 IOLockLock(assertionsArrayLock);
11490
11491 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11492 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11493 updateCPUBitAccounting(assertStruct);
11494 }
11495
11496 if (assertStruct->ownerString) {
11497 assertStruct->ownerString->release();
11498 assertStruct->ownerString = NULL;
11499 }
11500
11501 assertionsArray->removeObject(index);
11502 IOLockUnlock(assertionsArrayLock);
11503
11504 tabulate();
11505 return kIOReturnSuccess;
11506 }
11507
11508 /* PMAssertionsTracker::releaseAssertion
11509 * Releases an assertion and affects system behavior if appropiate.
11510 * Actual work happens on PM workloop.
11511 */
11512 IOReturn
11513 PMAssertionsTracker::releaseAssertion(
11514 IOPMDriverAssertionID _id)
11515 {
11516 if (owner && owner->pmPowerStateQueue) {
11517 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11518 }
11519 return kIOReturnSuccess;
11520 }
11521
11522 /* PMAssertionsTracker::handleSetAssertionLevel
11523 * Runs in PM workloop. Do not call directly.
11524 */
11525 IOReturn
11526 PMAssertionsTracker::handleSetAssertionLevel(
11527 IOPMDriverAssertionID _id,
11528 IOPMDriverAssertionLevel _level)
11529 {
11530 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
11531
11532 ASSERT_GATED();
11533
11534 if (!assertStruct) {
11535 return kIOReturnNotFound;
11536 }
11537
11538 IOLockLock(assertionsArrayLock);
11539 pmEventTimeStamp(&assertStruct->modifiedTime);
11540 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11541 (assertStruct->level != _level)) {
11542 if (_level == kIOPMDriverAssertionLevelOn) {
11543 assertStruct->assertCPUStartTime = mach_absolute_time();
11544 } else {
11545 updateCPUBitAccounting(assertStruct);
11546 }
11547 }
11548 assertStruct->level = _level;
11549 IOLockUnlock(assertionsArrayLock);
11550
11551 tabulate();
11552 return kIOReturnSuccess;
11553 }
11554
11555 /* PMAssertionsTracker::setAssertionLevel
11556 */
11557 IOReturn
11558 PMAssertionsTracker::setAssertionLevel(
11559 IOPMDriverAssertionID _id,
11560 IOPMDriverAssertionLevel _level)
11561 {
11562 if (owner && owner->pmPowerStateQueue) {
11563 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11564 (void *)(uintptr_t)_level, _id);
11565 }
11566
11567 return kIOReturnSuccess;
11568 }
11569
11570 IOReturn
11571 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11572 {
11573 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11574
11575 ASSERT_GATED();
11576
11577 if (new_user_levels != assertionsUser) {
11578 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11579 assertionsUser = new_user_levels;
11580 }
11581
11582 tabulate();
11583 return kIOReturnSuccess;
11584 }
11585
11586 IOReturn
11587 PMAssertionsTracker::setUserAssertionLevels(
11588 IOPMDriverAssertionType new_user_levels)
11589 {
11590 if (gIOPMWorkLoop) {
11591 gIOPMWorkLoop->runAction(
11592 OSMemberFunctionCast(
11593 IOWorkLoop::Action,
11594 this,
11595 &PMAssertionsTracker::handleSetUserAssertionLevels),
11596 this,
11597 (void *) &new_user_levels, NULL, NULL, NULL);
11598 }
11599
11600 return kIOReturnSuccess;
11601 }
11602
11603
11604 OSSharedPtr<OSArray>
11605 PMAssertionsTracker::copyAssertionsArray(void)
11606 {
11607 int count;
11608 int i;
11609 OSSharedPtr<OSArray> outArray = NULL;
11610
11611 if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11612 goto exit;
11613 }
11614 outArray = OSArray::withCapacity(count);
11615 if (!outArray) {
11616 goto exit;
11617 }
11618
11619 for (i = 0; i < count; i++) {
11620 const PMAssertStruct *_a = nullptr;
11621 OSValueObject<PMAssertStruct> *_d = nullptr;
11622 OSSharedPtr<OSDictionary> details;
11623
11624 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11625 if (_d && (_a = _d->getBytesNoCopy())) {
11626 OSSharedPtr<OSNumber> _n;
11627
11628 details = OSDictionary::withCapacity(7);
11629 if (!details) {
11630 continue;
11631 }
11632
11633 outArray->setObject(details.get());
11634
11635 _n = OSNumber::withNumber(_a->id, 64);
11636 if (_n) {
11637 details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11638 }
11639 _n = OSNumber::withNumber(_a->createdTime, 64);
11640 if (_n) {
11641 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11642 }
11643 _n = OSNumber::withNumber(_a->modifiedTime, 64);
11644 if (_n) {
11645 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11646 }
11647 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11648 if (_n) {
11649 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11650 }
11651 _n = OSNumber::withNumber(_a->level, 64);
11652 if (_n) {
11653 details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11654 }
11655 _n = OSNumber::withNumber(_a->assertionBits, 64);
11656 if (_n) {
11657 details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11658 }
11659
11660 if (_a->ownerString) {
11661 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11662 }
11663 }
11664 }
11665
11666 exit:
11667 return os::move(outArray);
11668 }
11669
11670 IOPMDriverAssertionType
11671 PMAssertionsTracker::getActivatedAssertions(void)
11672 {
11673 return assertionsCombined;
11674 }
11675
11676 IOPMDriverAssertionLevel
11677 PMAssertionsTracker::getAssertionLevel(
11678 IOPMDriverAssertionType type)
11679 {
11680 // FIXME: unused and also wrong
11681 if (type && ((type & assertionsKernel) == assertionsKernel)) {
11682 return kIOPMDriverAssertionLevelOn;
11683 } else {
11684 return kIOPMDriverAssertionLevelOff;
11685 }
11686 }
11687
11688 //*********************************************************************************
11689 //*********************************************************************************
11690 //*********************************************************************************
11691
11692
11693 static void
11694 pmEventTimeStamp(uint64_t *recordTS)
11695 {
11696 clock_sec_t tsec;
11697 clock_usec_t tusec;
11698
11699 if (!recordTS) {
11700 return;
11701 }
11702
11703 // We assume tsec fits into 32 bits; 32 bits holds enough
11704 // seconds for 136 years since the epoch in 1970.
11705 clock_get_calendar_microtime(&tsec, &tusec);
11706
11707
11708 // Pack the sec & microsec calendar time into a uint64_t, for fun.
11709 *recordTS = 0;
11710 *recordTS |= (uint32_t)tusec;
11711 *recordTS |= ((uint64_t)tsec << 32);
11712
11713 return;
11714 }
11715
11716 // MARK: -
11717 // MARK: IORootParent
11718
11719 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11720
11721 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11722
11723 // The reason that root domain needs a root parent is to facilitate demand
11724 // sleep, since a power change from the root parent cannot be vetoed.
11725 //
11726 // The above statement is no longer true since root domain now performs
11727 // demand sleep using overrides. But root parent remains to avoid changing
11728 // the power tree stacking. Root parent is parked at the max power state.
11729
11730
11731 static IOPMPowerState patriarchPowerStates[2] =
11732 {
11733 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11734 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11735 };
11736
11737 void
11738 IORootParent::initialize( void )
11739 {
11740
11741 gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
11742 gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
11743 gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
11744 gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
11745 gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
11746 gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
11747 gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
11748 gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
11749 gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
11750 gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
11751 gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
11752 gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
11753 gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
11754 gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
11755 gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
11756 gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
11757 gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
11758 gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
11759 gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
11760 gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
11761 gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
11762 gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
11763 gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
11764 gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
11765 gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
11766 gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
11767 gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
11768 gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
11769 gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
11770 gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
11771 gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
11772 gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
11773 gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
11774 gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
11775 gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
11776 gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
11777 gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
11778 gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
11779 gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
11780 gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
11781 gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
11782 gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
11783 gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
11784 gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
11785 }
11786
11787 bool
11788 IORootParent::start( IOService * nub )
11789 {
11790 IOService::start(nub);
11791 attachToParent( getRegistryRoot(), gIOPowerPlane );
11792 PMinit();
11793 registerPowerDriver(this, patriarchPowerStates, 2);
11794 makeUsable();
11795 return true;
11796 }
11797
11798 void
11799 IORootParent::shutDownSystem( void )
11800 {
11801 }
11802
11803 void
11804 IORootParent::restartSystem( void )
11805 {
11806 }
11807
11808 void
11809 IORootParent::sleepSystem( void )
11810 {
11811 }
11812
11813 void
11814 IORootParent::dozeSystem( void )
11815 {
11816 }
11817
11818 void
11819 IORootParent::sleepToDoze( void )
11820 {
11821 }
11822
11823 void
11824 IORootParent::wakeSystem( void )
11825 {
11826 }
11827
11828 OSSharedPtr<OSObject>
11829 IORootParent::copyProperty( const char * aKey) const
11830 {
11831 return IOService::copyProperty(aKey);
11832 }
11833
11834 uint32_t
11835 IOPMrootDomain::getWatchdogTimeout()
11836 {
11837 if (gSwdSleepWakeTimeout) {
11838 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11839 }
11840 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11841 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11842 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11843 } else {
11844 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11845 }
11846 }
11847
11848
11849 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11850 IOReturn
11851 IOPMrootDomain::restartWithStackshot()
11852 {
11853 takeStackshot(true);
11854
11855 return kIOReturnSuccess;
11856 }
11857
11858 void
11859 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
11860 {
11861 takeStackshot(wdogTrigger);
11862 }
11863
11864 void
11865 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
11866 {
11867 switch (tracePhase) {
11868 case kIOPMTracePointSleepStarted:
11869 *phaseString = "kIOPMTracePointSleepStarted";
11870 *description = "starting sleep";
11871 break;
11872
11873 case kIOPMTracePointSleepApplications:
11874 *phaseString = "kIOPMTracePointSleepApplications";
11875 *description = "notifying applications";
11876 break;
11877
11878 case kIOPMTracePointSleepPriorityClients:
11879 *phaseString = "kIOPMTracePointSleepPriorityClients";
11880 *description = "notifying clients about upcoming system capability changes";
11881 break;
11882
11883 case kIOPMTracePointSleepWillChangeInterests:
11884 *phaseString = "kIOPMTracePointSleepWillChangeInterests";
11885 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11886 break;
11887
11888 case kIOPMTracePointSleepPowerPlaneDrivers:
11889 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
11890 *description = "calling power state change callbacks";
11891 break;
11892
11893 case kIOPMTracePointSleepDidChangeInterests:
11894 *phaseString = "kIOPMTracePointSleepDidChangeInterests";
11895 *description = "calling rootDomain's clients about rootDomain's state changes";
11896 break;
11897
11898 case kIOPMTracePointSleepCapabilityClients:
11899 *phaseString = "kIOPMTracePointSleepCapabilityClients";
11900 *description = "notifying clients about current system capabilities";
11901 break;
11902
11903 case kIOPMTracePointSleepPlatformActions:
11904 *phaseString = "kIOPMTracePointSleepPlatformActions";
11905 *description = "calling Quiesce/Sleep action callbacks";
11906 break;
11907
11908 case kIOPMTracePointSleepCPUs:
11909 {
11910 *phaseString = "kIOPMTracePointSleepCPUs";
11911 #if defined(__i386__) || defined(__x86_64__)
11912 /*
11913 * We cannot use the getCPUNumber() method to get the cpu number, since
11914 * that cpu number is unrelated to the cpu number we need (we need the cpu
11915 * number as enumerated by the scheduler, NOT the CPU number enumerated
11916 * by ACPIPlatform as the CPUs are enumerated in MADT order).
11917 * Instead, pass the Mach processor pointer associated with the current
11918 * shutdown target so its associated cpu_id can be used in
11919 * processor_to_datastring.
11920 */
11921 if (currentShutdownTarget != NULL &&
11922 currentShutdownTarget->getMachProcessor() != NULL) {
11923 const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
11924 currentShutdownTarget->getMachProcessor());
11925 *description = sbuf;
11926 } else {
11927 *description = "halting all non-boot CPUs";
11928 }
11929 #else
11930 *description = "halting all non-boot CPUs";
11931 #endif
11932 break;
11933 }
11934 case kIOPMTracePointSleepPlatformDriver:
11935 *phaseString = "kIOPMTracePointSleepPlatformDriver";
11936 *description = "executing platform specific code";
11937 break;
11938
11939 case kIOPMTracePointHibernate:
11940 *phaseString = "kIOPMTracePointHibernate";
11941 *description = "writing the hibernation image";
11942 break;
11943
11944 case kIOPMTracePointSystemSleep:
11945 *phaseString = "kIOPMTracePointSystemSleep";
11946 *description = "in EFI/Bootrom after last point of entry to sleep";
11947 break;
11948
11949 case kIOPMTracePointWakePlatformDriver:
11950 *phaseString = "kIOPMTracePointWakePlatformDriver";
11951 *description = "executing platform specific code";
11952 break;
11953
11954
11955 case kIOPMTracePointWakePlatformActions:
11956 *phaseString = "kIOPMTracePointWakePlatformActions";
11957 *description = "calling Wake action callbacks";
11958 break;
11959
11960 case kIOPMTracePointWakeCPUs:
11961 *phaseString = "kIOPMTracePointWakeCPUs";
11962 *description = "starting non-boot CPUs";
11963 break;
11964
11965 case kIOPMTracePointWakeWillPowerOnClients:
11966 *phaseString = "kIOPMTracePointWakeWillPowerOnClients";
11967 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
11968 break;
11969
11970 case kIOPMTracePointWakeWillChangeInterests:
11971 *phaseString = "kIOPMTracePointWakeWillChangeInterests";
11972 *description = "calling rootDomain's clients about upcoming rootDomain's state changes";
11973 break;
11974
11975 case kIOPMTracePointWakeDidChangeInterests:
11976 *phaseString = "kIOPMTracePointWakeDidChangeInterests";
11977 *description = "calling rootDomain's clients about completed rootDomain's state changes";
11978 break;
11979
11980 case kIOPMTracePointWakePowerPlaneDrivers:
11981 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
11982 *description = "calling power state change callbacks";
11983 break;
11984
11985 case kIOPMTracePointWakeCapabilityClients:
11986 *phaseString = "kIOPMTracePointWakeCapabilityClients";
11987 *description = "informing clients about current system capabilities";
11988 break;
11989
11990 case kIOPMTracePointWakeApplications:
11991 *phaseString = "kIOPMTracePointWakeApplications";
11992 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
11993 break;
11994
11995 case kIOPMTracePointDarkWakeEntry:
11996 *phaseString = "kIOPMTracePointDarkWakeEntry";
11997 *description = "entering darkwake on way to sleep";
11998 break;
11999
12000 case kIOPMTracePointDarkWakeExit:
12001 *phaseString = "kIOPMTracePointDarkWakeExit";
12002 *description = "entering fullwake from darkwake";
12003 break;
12004
12005 default:
12006 *phaseString = NULL;
12007 *description = NULL;
12008 }
12009 }
12010
12011 void
12012 IOPMrootDomain::saveFailureData2File()
12013 {
12014 unsigned int len = 0;
12015 char failureStr[512];
12016 errno_t error;
12017 char *outbuf;
12018 OSNumber *statusCode;
12019 uint64_t pmStatusCode = 0;
12020 uint32_t phaseData = 0;
12021 uint32_t phaseDetail = 0;
12022 bool efiFailure = false;
12023
12024 OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
12025 statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
12026 if (statusCode) {
12027 pmStatusCode = statusCode->unsigned64BitValue();
12028 phaseData = pmStatusCode & 0xFFFFFFFF;
12029 phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
12030 if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
12031 LOG("Sleep Wake failure in EFI\n");
12032 efiFailure = true;
12033 failureStr[0] = 0;
12034 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);
12035 len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12036 }
12037 }
12038
12039 if (!efiFailure) {
12040 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12041 swd_flags |= SWD_BOOT_BY_SW_WDOG;
12042 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12043 // dump panic will handle saving nvram data
12044 return;
12045 }
12046
12047 /* Keeping this around for capturing data during power
12048 * button press */
12049
12050 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12051 DLOG("No sleep wake failure string\n");
12052 return;
12053 }
12054 if (len == 0) {
12055 DLOG("Ignoring zero byte SleepWake failure string\n");
12056 goto exit;
12057 }
12058
12059 // if PMStatus code is zero, delete stackshot and return
12060 if (statusCode) {
12061 if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12062 // there was no sleep wake failure
12063 // this can happen if delete stackshot was called
12064 // before take stackshot completed. Let us delete any
12065 // sleep wake failure data in nvram
12066 DLOG("Deleting stackshot on successful wake\n");
12067 deleteStackshot();
12068 return;
12069 }
12070 }
12071
12072 if (len > sizeof(failureStr)) {
12073 len = sizeof(failureStr);
12074 }
12075 failureStr[0] = 0;
12076 PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12077 }
12078 if (failureStr[0] != 0) {
12079 error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12080 if (error) {
12081 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12082 } else {
12083 DLOG("Saved SleepWake failure string to file.\n");
12084 }
12085 }
12086
12087 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12088 goto exit;
12089 }
12090
12091 if (swd_buffer) {
12092 unsigned int len = 0;
12093 errno_t error;
12094 char nvram_var_name_buffer[20];
12095 unsigned int concat_len = 0;
12096 swd_hdr *hdr = NULL;
12097
12098
12099 hdr = (swd_hdr *)swd_buffer;
12100 outbuf = (char *)hdr + hdr->spindump_offset;
12101 OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12102
12103 for (int i = 0; i < 8; i++) {
12104 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12105 if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12106 LOG("No SleepWake blob to read beyond chunk %d\n", i);
12107 break;
12108 }
12109 if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12110 PERemoveNVRAMProperty(nvram_var_name_buffer);
12111 LOG("Could not read the property :-(\n");
12112 break;
12113 }
12114 PERemoveNVRAMProperty(nvram_var_name_buffer);
12115 concat_len += len;
12116 }
12117 LOG("Concatenated length for the SWD blob %d\n", concat_len);
12118
12119 if (concat_len) {
12120 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12121 if (error) {
12122 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12123 } else {
12124 LOG("Saved SleepWake zipped data to file.\n");
12125 }
12126 } else {
12127 // There is a sleep wake failure string but no stackshot
12128 // Write a placeholder stacks file so that swd runs
12129 snprintf(outbuf, 20, "%s", "No stackshot data\n");
12130 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12131 if (error) {
12132 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12133 } else {
12134 LOG("Saved SleepWake zipped data to file.\n");
12135 }
12136 }
12137 } else {
12138 LOG("No buffer allocated to save failure stackshot\n");
12139 }
12140
12141
12142 gRootDomain->swd_lock = 0;
12143 exit:
12144 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12145 return;
12146 }
12147
12148
12149 void
12150 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12151 {
12152 OSSharedPtr<IORegistryIterator> iter;
12153 OSSharedPtr<const OSSymbol> kextName = NULL;
12154 IORegistryEntry * entry;
12155 IOService * node;
12156 bool nodeFound = false;
12157
12158 const void * callMethod = NULL;
12159 const char * objectName = NULL;
12160 uint32_t timeout = getWatchdogTimeout();
12161 const char * phaseString = NULL;
12162 const char * phaseDescription = NULL;
12163
12164 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12165 uint32_t tracePhase = pmTracer->getTracePhase();
12166
12167 *thread = NULL;
12168 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12169 snprintf(failureStr, strLen, "Sleep transition timed out after %d seconds", timeout);
12170 } else {
12171 snprintf(failureStr, strLen, "Wake transition timed out after %d seconds", timeout);
12172 }
12173 tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12174
12175 if (notifierThread) {
12176 if (notifier && (notifier->identifier)) {
12177 objectName = notifier->identifier->getCStringNoCopy();
12178 }
12179 *thread = notifierThread;
12180 } else {
12181 iter = IORegistryIterator::iterateOver(
12182 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12183
12184 if (iter) {
12185 while ((entry = iter->getNextObject())) {
12186 node = OSDynamicCast(IOService, entry);
12187 if (!node) {
12188 continue;
12189 }
12190 if (OSDynamicCast(IOPowerConnection, node)) {
12191 continue;
12192 }
12193
12194 if (node->getBlockingDriverCall(thread, &callMethod)) {
12195 nodeFound = true;
12196 break;
12197 }
12198 }
12199 }
12200 if (nodeFound) {
12201 kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12202 if (kextName) {
12203 objectName = kextName->getCStringNoCopy();
12204 }
12205 }
12206 }
12207 if (phaseDescription) {
12208 strlcat(failureStr, " while ", strLen);
12209 strlcat(failureStr, phaseDescription, strLen);
12210 strlcat(failureStr, ".", strLen);
12211 }
12212 if (objectName) {
12213 strlcat(failureStr, " Suspected bundle: ", strLen);
12214 strlcat(failureStr, objectName, strLen);
12215 strlcat(failureStr, ".", strLen);
12216 }
12217 if (*thread) {
12218 char threadName[40];
12219 snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12220 strlcat(failureStr, threadName, strLen);
12221 }
12222
12223 DLOG("%s\n", failureStr);
12224 }
12225
12226 struct swd_stackshot_compressed_data {
12227 z_output_func zoutput;
12228 size_t zipped;
12229 uint64_t totalbytes;
12230 uint64_t lastpercent;
12231 IOReturn error;
12232 unsigned outremain;
12233 unsigned outlen;
12234 unsigned writes;
12235 Bytef * outbuf;
12236 };
12237 struct swd_stackshot_compressed_data swd_zip_var = { };
12238
12239 static void *
12240 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12241 {
12242 void *result;
12243 LOG("Alloc in zipping %d items of size %d\n", items, size);
12244
12245 result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12246 swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12247 LOG("Offset %zu\n", swd_zs_zoffset);
12248 return result;
12249 }
12250
12251 static int
12252 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12253 {
12254 unsigned len;
12255
12256 len = strm->avail_in;
12257
12258 if (len > size) {
12259 len = size;
12260 }
12261 if (len == 0) {
12262 return 0;
12263 }
12264
12265 if (strm->next_in != (Bytef *) strm) {
12266 memcpy(buf, strm->next_in, len);
12267 } else {
12268 bzero(buf, len);
12269 }
12270
12271 strm->adler = z_crc32(strm->adler, buf, len);
12272
12273 strm->avail_in -= len;
12274 strm->next_in += len;
12275 strm->total_in += len;
12276
12277 return (int)len;
12278 }
12279
12280 static int
12281 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12282 {
12283 unsigned int i = 0;
12284 // if outlen > max size don't add to the buffer
12285 assert(buf != NULL);
12286 if (strm && buf) {
12287 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12288 LOG("No space to GZIP... not writing to NVRAM\n");
12289 return len;
12290 }
12291 }
12292 for (i = 0; i < len; i++) {
12293 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12294 }
12295 swd_zip_var.outlen += len;
12296 return len;
12297 }
12298
12299 static void
12300 swd_zs_free(void * __unused ref, void * __unused ptr)
12301 {
12302 }
12303
12304 static int
12305 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12306 {
12307 int wbits = 12;
12308 int memlevel = 3;
12309
12310 if (((unsigned int) numBytes) != numBytes) {
12311 return 0;
12312 }
12313
12314 if (!swd_zs.zalloc) {
12315 swd_zs.zalloc = swd_zs_alloc;
12316 swd_zs.zfree = swd_zs_free;
12317 if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12318 // allocation failed
12319 bzero(&swd_zs, sizeof(swd_zs));
12320 // swd_zs_zoffset = 0;
12321 } else {
12322 LOG("PMRD inited the zlib allocation routines\n");
12323 }
12324 }
12325
12326 swd_zip_var.zipped = 0;
12327 swd_zip_var.totalbytes = 0; // should this be the max that we have?
12328 swd_zip_var.lastpercent = 0;
12329 swd_zip_var.error = kIOReturnSuccess;
12330 swd_zip_var.outremain = 0;
12331 swd_zip_var.outlen = 0;
12332 swd_zip_var.writes = 0;
12333 swd_zip_var.outbuf = (Bytef *)outPtr;
12334
12335 swd_zip_var.totalbytes = numBytes;
12336
12337 swd_zs.avail_in = 0;
12338 swd_zs.next_in = NULL;
12339 swd_zs.avail_out = 0;
12340 swd_zs.next_out = NULL;
12341
12342 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12343
12344 z_stream *zs;
12345 int zr;
12346 zs = &swd_zs;
12347
12348 while (swd_zip_var.error >= 0) {
12349 if (!zs->avail_in) {
12350 zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12351 zs->avail_in = (unsigned int) numBytes;
12352 }
12353 if (!zs->avail_out) {
12354 zs->next_out = (Bytef *)zs;
12355 zs->avail_out = UINT32_MAX;
12356 }
12357 zr = deflate(zs, Z_NO_FLUSH);
12358 if (Z_STREAM_END == zr) {
12359 break;
12360 }
12361 if (zr != Z_OK) {
12362 LOG("ZERR %d\n", zr);
12363 swd_zip_var.error = zr;
12364 } else {
12365 if (zs->total_in == numBytes) {
12366 break;
12367 }
12368 }
12369 }
12370
12371 //now flush the stream
12372 while (swd_zip_var.error >= 0) {
12373 if (!zs->avail_out) {
12374 zs->next_out = (Bytef *)zs;
12375 zs->avail_out = UINT32_MAX;
12376 }
12377 zr = deflate(zs, Z_FINISH);
12378 if (Z_STREAM_END == zr) {
12379 break;
12380 }
12381 if (zr != Z_OK) {
12382 LOG("ZERR %d\n", zr);
12383 swd_zip_var.error = zr;
12384 } else {
12385 if (zs->total_in == numBytes) {
12386 LOG("Total output size %d\n", swd_zip_var.outlen);
12387 break;
12388 }
12389 }
12390 }
12391
12392 return swd_zip_var.outlen;
12393 }
12394
12395 void
12396 IOPMrootDomain::deleteStackshot()
12397 {
12398 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12399 // takeStackshot hasn't completed
12400 return;
12401 }
12402 LOG("Deleting any sleepwake failure data in nvram\n");
12403
12404 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12405 char nvram_var_name_buf[20];
12406 for (int i = 0; i < 8; i++) {
12407 snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12408 if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12409 LOG("Removing %s returned false\n", nvram_var_name_buf);
12410 }
12411 }
12412 // force NVRAM sync
12413 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12414 DLOG("Failed to force nvram sync\n");
12415 }
12416 gRootDomain->swd_lock = 0;
12417 }
12418
12419 void
12420 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12421 {
12422 swd_hdr * hdr = NULL;
12423 int cnt = 0;
12424 int max_cnt;
12425 pid_t pid = 0;
12426 kern_return_t kr = KERN_SUCCESS;
12427 uint64_t flags;
12428
12429 char * dstAddr;
12430 uint32_t size;
12431 uint32_t bytesRemaining;
12432 unsigned bytesWritten = 0;
12433
12434 char failureStr[512];
12435 thread_t thread = NULL;
12436 const char * swfPanic = "swfPanic";
12437
12438 uint32_t bufSize;
12439 int success = 0;
12440
12441 #if defined(__i386__) || defined(__x86_64__)
12442 const bool concise = false;
12443 #else
12444 const bool concise = true;
12445 #endif
12446
12447 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12448 return;
12449 }
12450
12451 failureStr[0] = 0;
12452 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12453 return;
12454 }
12455
12456 if (wdogTrigger) {
12457 getFailureData(&thread, failureStr, sizeof(failureStr));
12458
12459 if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12460 goto skip_stackshot;
12461 }
12462 } else {
12463 AbsoluteTime now;
12464 uint64_t nsec;
12465 clock_get_uptime(&now);
12466 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12467 absolutetime_to_nanoseconds(now, &nsec);
12468 snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12469 }
12470
12471 if (swd_buffer == NULL) {
12472 sleepWakeDebugMemAlloc();
12473 if (swd_buffer == NULL) {
12474 return;
12475 }
12476 }
12477 hdr = (swd_hdr *)swd_buffer;
12478 bufSize = hdr->alloc_size;
12479
12480 dstAddr = (char*)hdr + hdr->spindump_offset;
12481 flags = STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_THREAD_WAITINFO | STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12482
12483 /* If not wdogTrigger only take kernel tasks stackshot
12484 */
12485 if (wdogTrigger) {
12486 pid = -1;
12487 max_cnt = 3;
12488 } else {
12489 pid = 0;
12490 max_cnt = 2;
12491 }
12492
12493 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12494 * If we run out of space, take stackshot with only kernel task
12495 */
12496 while (success == 0 && cnt < max_cnt) {
12497 bytesRemaining = bufSize - hdr->spindump_offset;
12498 cnt++;
12499 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12500
12501 size = bytesRemaining;
12502 kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12503 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12504 kr, pid, size, flags, bytesWritten);
12505 if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12506 if (pid == -1) {
12507 pid = 0;
12508 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12509 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12510 } else {
12511 LOG("Insufficient buffer size for only kernel task\n");
12512 break;
12513 }
12514 }
12515 if (kr == KERN_SUCCESS) {
12516 if (bytesWritten == 0) {
12517 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12518 continue;
12519 }
12520 bytesRemaining -= bytesWritten;
12521 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12522
12523 memset(hdr->reason, 0x20, sizeof(hdr->reason));
12524
12525 // Compress stackshot and save to NVRAM
12526 {
12527 char *outbuf = (char *)swd_compressed_buffer;
12528 int outlen = 0;
12529 int num_chunks = 0;
12530 int max_chunks = 0;
12531 int leftover = 0;
12532 char nvram_var_name_buffer[20];
12533
12534 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12535
12536 if (outlen) {
12537 max_chunks = outlen / (2096 - 200);
12538 leftover = outlen % (2096 - 200);
12539
12540 if (max_chunks < 8) {
12541 for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
12542 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12543 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
12544 LOG("Failed to update NVRAM %d\n", num_chunks);
12545 break;
12546 }
12547 }
12548 if (leftover) {
12549 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12550 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
12551 LOG("Failed to update NVRAM with leftovers\n");
12552 }
12553 }
12554 success = 1;
12555 LOG("Successfully saved stackshot to NVRAM\n");
12556 } else {
12557 if (pid == -1) {
12558 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12559 pid = 0;
12560 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12561 LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
12562 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12563 } else {
12564 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12565 break;
12566 }
12567 }
12568 }
12569 }
12570 }
12571 }
12572
12573 if (failureStr[0]) {
12574 // append sleep-wake failure code
12575 char traceCode[80];
12576 snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
12577 pmTracer->getTraceData(), pmTracer->getTracePhase());
12578 strlcat(failureStr, traceCode, sizeof(failureStr));
12579 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
12580 DLOG("Failed to write SleepWake failure string\n");
12581 }
12582 }
12583
12584 // force NVRAM sync
12585 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12586 DLOG("Failed to force nvram sync\n");
12587 }
12588
12589 skip_stackshot:
12590 if (wdogTrigger) {
12591 if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
12592 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
12593 // If current boot is due to this watch dog trigger restart in previous boot,
12594 // then don't trigger again until at least 1 successful sleep & wake.
12595 if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
12596 LOG("Shutting down due to repeated Sleep/Wake failures\n");
12597 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12598 PEHaltRestart(kPEHaltCPU);
12599 return;
12600 }
12601 }
12602 if (gSwdPanic == 0) {
12603 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12604 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12605 PEHaltRestart(kPERestartCPU);
12606 }
12607 }
12608 if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12609 DLOG("Failed to write SleepWake failure panic key\n");
12610 }
12611 #if defined(__x86_64__)
12612 if (thread) {
12613 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12614 } else
12615 #endif /* defined(__x86_64__) */
12616 {
12617 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12618 }
12619 } else {
12620 gRootDomain->swd_lock = 0;
12621 return;
12622 }
12623 }
12624
12625 void
12626 IOPMrootDomain::sleepWakeDebugMemAlloc()
12627 {
12628 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12629
12630 swd_hdr *hdr = NULL;
12631 void *bufPtr = NULL;
12632
12633 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12634
12635
12636 if (kIOSleepWakeWdogOff & gIOKitDebug) {
12637 return;
12638 }
12639
12640 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12641 return;
12642 }
12643
12644 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12645 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12646 size);
12647 if (memDesc == NULL) {
12648 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12649 goto exit;
12650 }
12651
12652 bufPtr = memDesc->getBytesNoCopy();
12653
12654 // Carve out memory for zlib routines
12655 swd_zs_zmem = (vm_offset_t)bufPtr;
12656 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12657
12658 // Carve out memory for compressed stackshots
12659 swd_compressed_buffer = bufPtr;
12660 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12661
12662 // Remaining is used for holding stackshot
12663 hdr = (swd_hdr *)bufPtr;
12664 memset(hdr, 0, sizeof(swd_hdr));
12665
12666 hdr->signature = SWD_HDR_SIGNATURE;
12667 hdr->alloc_size = SWD_STACKSHOT_SIZE;
12668
12669 hdr->spindump_offset = sizeof(swd_hdr);
12670 swd_buffer = (void *)hdr;
12671 swd_memDesc = os::move(memDesc);
12672 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
12673
12674 exit:
12675 gRootDomain->swd_lock = 0;
12676 }
12677
12678 void
12679 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12680 {
12681 #if UNUSED
12682 vm_size_t size = SWD_SPINDUMP_SIZE;
12683
12684 swd_hdr *hdr = NULL;
12685
12686 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12687
12688 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12689 return;
12690 }
12691
12692 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12693 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12694 SWD_SPINDUMP_SIZE);
12695
12696 if (memDesc == NULL) {
12697 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12698 goto exit;
12699 }
12700
12701
12702 hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12703 memset(hdr, 0, sizeof(swd_hdr));
12704
12705 hdr->signature = SWD_HDR_SIGNATURE;
12706 hdr->alloc_size = size;
12707
12708 hdr->spindump_offset = sizeof(swd_hdr);
12709 swd_spindump_buffer = (void *)hdr;
12710 swd_spindump_memDesc = os::move(memDesc);
12711
12712 exit:
12713 gRootDomain->swd_lock = 0;
12714 #endif /* UNUSED */
12715 }
12716
12717 void
12718 IOPMrootDomain::sleepWakeDebugEnableWdog()
12719 {
12720 }
12721
12722 bool
12723 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12724 {
12725 return !systemBooting && !systemShutdown && !gWillShutdown;
12726 }
12727
12728 void
12729 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12730 {
12731 swd_hdr *hdr = NULL;
12732 errno_t error = EIO;
12733
12734 if (swd_spindump_buffer && gSpinDumpBufferFull) {
12735 hdr = (swd_hdr *)swd_spindump_buffer;
12736
12737 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12738 (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12739
12740 if (error) {
12741 return;
12742 }
12743
12744 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12745 (char*)hdr + offsetof(swd_hdr, UUID),
12746 sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12747
12748 gSpinDumpBufferFull = false;
12749 }
12750 }
12751
12752 errno_t
12753 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12754 {
12755 struct vnode *vp = NULL;
12756 vfs_context_t ctx = vfs_context_create(vfs_context_current());
12757 kauth_cred_t cred = vfs_context_ucred(ctx);
12758 struct vnode_attr va;
12759 errno_t error = EIO;
12760
12761 if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
12762 S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
12763 LOG("Failed to open the file %s\n", name);
12764 swd_flags |= SWD_FILEOP_ERROR;
12765 goto exit;
12766 }
12767 VATTR_INIT(&va);
12768 VATTR_WANTED(&va, va_nlink);
12769 /* Don't dump to non-regular files or files with links. */
12770 if (vp->v_type != VREG ||
12771 vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
12772 LOG("Bailing as this is not a regular file\n");
12773 swd_flags |= SWD_FILEOP_ERROR;
12774 goto exit;
12775 }
12776 VATTR_INIT(&va);
12777 VATTR_SET(&va, va_data_size, 0);
12778 vnode_setattr(vp, &va, ctx);
12779
12780
12781 if (buf != NULL) {
12782 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12783 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12784 if (error != 0) {
12785 LOG("Failed to save sleep wake log. err 0x%x\n", error);
12786 swd_flags |= SWD_FILEOP_ERROR;
12787 } else {
12788 DLOG("Saved %d bytes to file %s\n", len, name);
12789 }
12790 }
12791
12792 exit:
12793 if (vp) {
12794 vnode_close(vp, FWRITE, ctx);
12795 }
12796 if (ctx) {
12797 vfs_context_rele(ctx);
12798 }
12799
12800 return error;
12801 }
12802
12803 #else /* defined(__i386__) || defined(__x86_64__) */
12804
12805 void
12806 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12807 {
12808 if (restart) {
12809 if (gSwdPanic == 0) {
12810 return;
12811 }
12812 panic("Sleep/Wake hang detected");
12813 return;
12814 }
12815 }
12816
12817 void
12818 IOPMrootDomain::takeStackshot(bool restart)
12819 {
12820 #pragma unused(restart)
12821 }
12822
12823 void
12824 IOPMrootDomain::deleteStackshot()
12825 {
12826 }
12827
12828 void
12829 IOPMrootDomain::sleepWakeDebugMemAlloc()
12830 {
12831 }
12832
12833 void
12834 IOPMrootDomain::saveFailureData2File()
12835 {
12836 }
12837
12838 void
12839 IOPMrootDomain::sleepWakeDebugEnableWdog()
12840 {
12841 }
12842
12843 bool
12844 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12845 {
12846 return false;
12847 }
12848
12849 void
12850 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12851 {
12852 }
12853
12854 errno_t
12855 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12856 {
12857 return 0;
12858 }
12859
12860 #endif /* defined(__i386__) || defined(__x86_64__) */
12861
12862