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