1 /*
2 * Copyright (c) 1998-2021 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #define IOKIT_ENABLE_SHARED_PTR
30
31 #include <libkern/c++/OSAllocation.h>
32 #include <libkern/c++/OSKext.h>
33 #include <libkern/c++/OSMetaClass.h>
34 #include <libkern/OSAtomic.h>
35 #include <libkern/OSDebug.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommandGate.h>
38 #include <IOKit/IOTimerEventSource.h>
39 #include <IOKit/IOPlatformExpert.h>
40 #include <IOKit/IOCPU.h>
41 #include <IOKit/IOPlatformActions.h>
42 #include <IOKit/IOKitDebug.h>
43 #include <IOKit/IOTimeStamp.h>
44 #include <IOKit/pwr_mgt/IOPMlog.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
46 #include <IOKit/pwr_mgt/IOPMPrivate.h>
47 #include <IOKit/IODeviceTreeSupport.h>
48 #include <IOKit/IOMessage.h>
49 #include <IOKit/IOReturn.h>
50 #include <IOKit/IONVRAM.h>
51 #include "RootDomainUserClient.h"
52 #include "IOKit/pwr_mgt/IOPowerConnection.h"
53 #include "IOPMPowerStateQueue.h"
54 #include <IOKit/IOCatalogue.h>
55 #include <IOKit/IOReportMacros.h>
56 #include <IOKit/IOLib.h>
57 #include <IOKit/IOKitKeys.h>
58 #include <IOKit/IOUserServer.h>
59 #include "IOKitKernelInternal.h"
60 #if HIBERNATION
61 #include <IOKit/IOHibernatePrivate.h>
62 #endif /* HIBERNATION */
63 #include <machine/machine_routines.h>
64 #include <console/video_console.h>
65 #include <sys/syslog.h>
66 #include <sys/sysctl.h>
67 #include <sys/vnode.h>
68 #include <sys/vnode_internal.h>
69 #include <sys/fcntl.h>
70 #include <os/log.h>
71 #include <pexpert/protos.h>
72 #include <AssertMacros.h>
73
74 #include <sys/time.h>
75 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
76 #include "IOServicePMPrivate.h"
77
78 #include <libkern/zlib.h>
79 #include <os/cpp_util.h>
80 #include <os/atomic_private.h>
81 #include <libkern/c++/OSBoundedArrayRef.h>
82 #include <libkern/coreanalytics/coreanalytics.h>
83
84 #if DEVELOPMENT || DEBUG
85 #include <os/system_event_log.h>
86 #endif /* DEVELOPMENT || DEBUG */
87
88 __BEGIN_DECLS
89 #include <mach/shared_region.h>
90 #include <kern/clock.h>
91 #include <vm/vm_pageout_xnu.h>
92 __END_DECLS
93
94 #if defined(__i386__) || defined(__x86_64__)
95 __BEGIN_DECLS
96 #include "IOPMrootDomainInternal.h"
97 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
98 __END_DECLS
99 #endif
100
101 #define kIOPMrootDomainClass "IOPMrootDomain"
102 #define LOG_PREFIX "PMRD: "
103
104
105 #define MSG(x...) \
106 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
107
108 #define LOG(x...) \
109 do { kprintf(LOG_PREFIX x); } while (false)
110
111 #if DEVELOPMENT || DEBUG
112 #define DEBUG_LOG(x...) do { \
113 if (kIOLogPMRootDomain & gIOKitDebug) \
114 kprintf(LOG_PREFIX x); \
115 os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
116 } while (false)
117 #else
118 #define DEBUG_LOG(x...)
119 #endif
120
121 #define DLOG(x...) do { \
122 if (kIOLogPMRootDomain & gIOKitDebug) \
123 IOLog(LOG_PREFIX x); \
124 else \
125 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
126 } while (false)
127
128 #define DMSG(x...) do { \
129 if (kIOLogPMRootDomain & gIOKitDebug) { \
130 kprintf(LOG_PREFIX x); \
131 } \
132 } while (false)
133
134
135 #define _LOG(x...)
136
137 #define CHECK_THREAD_CONTEXT
138 #ifdef CHECK_THREAD_CONTEXT
139 static IOWorkLoop * gIOPMWorkLoop = NULL;
140 #define ASSERT_GATED() \
141 do { \
142 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
143 panic("RootDomain: not inside PM gate"); \
144 } \
145 } while(false)
146 #else
147 #define ASSERT_GATED()
148 #endif /* CHECK_THREAD_CONTEXT */
149
150 #define CAP_LOSS(c) \
151 (((_pendingCapability & (c)) == 0) && \
152 ((_currentCapability & (c)) != 0))
153
154 #define CAP_GAIN(c) \
155 (((_currentCapability & (c)) == 0) && \
156 ((_pendingCapability & (c)) != 0))
157
158 #define CAP_CHANGE(c) \
159 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
160
161 #define CAP_CURRENT(c) \
162 ((_currentCapability & (c)) != 0)
163
164 #define CAP_HIGHEST(c) \
165 ((_highestCapability & (c)) != 0)
166
167 #define CAP_PENDING(c) \
168 ((_pendingCapability & (c)) != 0)
169
170 // rdar://problem/9157444
171 #if defined(__i386__) || defined(__x86_64__)
172 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 20
173 #endif
174
175 // Event types for IOPMPowerStateQueue::submitPowerEvent()
176 enum {
177 kPowerEventFeatureChanged = 1, // 1
178 kPowerEventReceivedPowerNotification, // 2
179 kPowerEventSystemBootCompleted, // 3
180 kPowerEventSystemShutdown, // 4
181 kPowerEventUserDisabledSleep, // 5
182 kPowerEventRegisterSystemCapabilityClient, // 6
183 kPowerEventRegisterKernelCapabilityClient, // 7
184 kPowerEventPolicyStimulus, // 8
185 kPowerEventAssertionCreate, // 9
186 kPowerEventAssertionRelease, // 10
187 kPowerEventAssertionSetLevel, // 11
188 kPowerEventQueueSleepWakeUUID, // 12
189 kPowerEventPublishSleepWakeUUID, // 13
190 kPowerEventSetDisplayPowerOn, // 14
191 kPowerEventPublishWakeType, // 15
192 kPowerEventAOTEvaluate // 16
193 };
194
195 // For evaluatePolicy()
196 // List of stimuli that affects the root domain policy.
197 enum {
198 kStimulusDisplayWranglerSleep, // 0
199 kStimulusDisplayWranglerWake, // 1
200 kStimulusAggressivenessChanged, // 2
201 kStimulusDemandSystemSleep, // 3
202 kStimulusAllowSystemSleepChanged, // 4
203 kStimulusDarkWakeActivityTickle, // 5
204 kStimulusDarkWakeEntry, // 6
205 kStimulusDarkWakeReentry, // 7
206 kStimulusDarkWakeEvaluate, // 8
207 kStimulusNoIdleSleepPreventers, // 9
208 kStimulusEnterUserActiveState, // 10
209 kStimulusLeaveUserActiveState // 11
210 };
211
212 // Internal power state change reasons
213 // Must be less than kIOPMSleepReasonClamshell=101
214 enum {
215 kCPSReasonNone = 0, // 0
216 kCPSReasonInit, // 1
217 kCPSReasonWake, // 2
218 kCPSReasonIdleSleepPrevent, // 3
219 kCPSReasonIdleSleepAllow, // 4
220 kCPSReasonPowerOverride, // 5
221 kCPSReasonPowerDownCancel, // 6
222 kCPSReasonAOTExit, // 7
223 kCPSReasonAdjustPowerState, // 8
224 kCPSReasonDarkWakeCannotSleep, // 9
225 kCPSReasonIdleSleepEnabled, // 10
226 kCPSReasonEvaluatePolicy, // 11
227 kCPSReasonSustainFullWake, // 12
228 kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1)
229 };
230
231 extern "C" {
232 IOReturn OSKextSystemSleepOrWake( UInt32 );
233 }
234 extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
235 extern "C" addr64_t kvtophys(vm_offset_t va);
236 extern "C" boolean_t kdp_has_polled_corefile();
237
238 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
239 static void notifySystemShutdown( IOService * root, uint32_t messageType );
240 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
241 static void pmEventTimeStamp(uint64_t *recordTS);
242 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
243 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
244 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address);
245
246 static int IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt);
247 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
248 #define YMDTF "%04d/%02d/%d %02d:%02d:%02d"
249 #define YMDT(cal) ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
250
251 // "IOPMSetSleepSupported" callPlatformFunction name
252 static OSSharedPtr<const OSSymbol> sleepSupportedPEFunction;
253 static OSSharedPtr<const OSSymbol> sleepMessagePEFunction;
254 static OSSharedPtr<const OSSymbol> gIOPMWakeTypeUserKey;
255
256 static OSSharedPtr<const OSSymbol> gIOPMPSExternalConnectedKey;
257 static OSSharedPtr<const OSSymbol> gIOPMPSExternalChargeCapableKey;
258 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryInstalledKey;
259 static OSSharedPtr<const OSSymbol> gIOPMPSIsChargingKey;
260 static OSSharedPtr<const OSSymbol> gIOPMPSAtWarnLevelKey;
261 static OSSharedPtr<const OSSymbol> gIOPMPSAtCriticalLevelKey;
262 static OSSharedPtr<const OSSymbol> gIOPMPSCurrentCapacityKey;
263 static OSSharedPtr<const OSSymbol> gIOPMPSMaxCapacityKey;
264 static OSSharedPtr<const OSSymbol> gIOPMPSDesignCapacityKey;
265 static OSSharedPtr<const OSSymbol> gIOPMPSTimeRemainingKey;
266 static OSSharedPtr<const OSSymbol> gIOPMPSAmperageKey;
267 static OSSharedPtr<const OSSymbol> gIOPMPSVoltageKey;
268 static OSSharedPtr<const OSSymbol> gIOPMPSCycleCountKey;
269 static OSSharedPtr<const OSSymbol> gIOPMPSMaxErrKey;
270 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterInfoKey;
271 static OSSharedPtr<const OSSymbol> gIOPMPSLocationKey;
272 static OSSharedPtr<const OSSymbol> gIOPMPSErrorConditionKey;
273 static OSSharedPtr<const OSSymbol> gIOPMPSManufacturerKey;
274 static OSSharedPtr<const OSSymbol> gIOPMPSManufactureDateKey;
275 static OSSharedPtr<const OSSymbol> gIOPMPSModelKey;
276 static OSSharedPtr<const OSSymbol> gIOPMPSSerialKey;
277 static OSSharedPtr<const OSSymbol> gIOPMPSLegacyBatteryInfoKey;
278 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryHealthKey;
279 static OSSharedPtr<const OSSymbol> gIOPMPSHealthConfidenceKey;
280 static OSSharedPtr<const OSSymbol> gIOPMPSCapacityEstimatedKey;
281 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryChargeStatusKey;
282 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryTemperatureKey;
283 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsKey;
284 static OSSharedPtr<const OSSymbol> gIOPMPSChargerConfigurationKey;
285 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsIDKey;
286 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsWattsKey;
287 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsRevisionKey;
288 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSerialNumberKey;
289 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsFamilyKey;
290 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsAmperageKey;
291 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsDescriptionKey;
292 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsPMUConfigurationKey;
293 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSourceIDKey;
294 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsErrorFlagsKey;
295 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSharedSourceKey;
296 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsCloakedKey;
297 static OSSharedPtr<const OSSymbol> gIOPMPSInvalidWakeSecondsKey;
298 static OSSharedPtr<const OSSymbol> gIOPMPSPostChargeWaitSecondsKey;
299 static OSSharedPtr<const OSSymbol> gIOPMPSPostDishargeWaitSecondsKey;
300
301 #define kIOSleepSupportedKey "IOSleepSupported"
302 #define kIOPMSystemCapabilitiesKey "System Capabilities"
303 #define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
304
305 #define kIORequestWranglerIdleKey "IORequestIdle"
306 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
307
308 #define kIOSleepWakeFailureString "SleepWakeFailureString"
309 #define kIOEFIBootRomFailureKey "wake-failure"
310 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic"
311
312 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
313 | kIOPMSupportedOnBatt \
314 | kIOPMSupportedOnUPS)
315
316 #define kLocalEvalClamshellCommand (1 << 15)
317 #define kIdleSleepRetryInterval (3 * 60 * 1000)
318
319 // Minimum time in milliseconds after AP wake that we allow idle timer to expire.
320 // We impose this minimum to avoid race conditions in the AP wake path where
321 // userspace clients are not able to acquire power assertions before the idle timer expires.
322 #define kMinimumTimeBeforeIdleSleep 1000
323
324 #define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID)
325
326 enum {
327 kWranglerPowerStateMin = 0,
328 kWranglerPowerStateSleep = 2,
329 kWranglerPowerStateDim = 3,
330 kWranglerPowerStateMax = 4
331 };
332
333 enum {
334 OFF_STATE = 0,
335 RESTART_STATE = 1,
336 SLEEP_STATE = 2,
337 AOT_STATE = 3,
338 ON_STATE = 4,
339 NUM_POWER_STATES
340 };
341
342 const char *
getPowerStateString(uint32_t state)343 getPowerStateString( uint32_t state )
344 {
345 #define POWER_STATE(x) {(uint32_t) x, #x}
346
347 static const IONamedValue powerStates[] = {
348 POWER_STATE( OFF_STATE ),
349 POWER_STATE( RESTART_STATE ),
350 POWER_STATE( SLEEP_STATE ),
351 POWER_STATE( AOT_STATE ),
352 POWER_STATE( ON_STATE ),
353 { 0, NULL }
354 };
355 return IOFindNameForValue(state, powerStates);
356 }
357
358 #define ON_POWER kIOPMPowerOn
359 #define RESTART_POWER kIOPMRestart
360 #define SLEEP_POWER kIOPMAuxPowerOn
361
362 static IOPMPowerState
363 ourPowerStates[NUM_POWER_STATES] =
364 {
365 { .version = 1,
366 .capabilityFlags = 0,
367 .outputPowerCharacter = 0,
368 .inputPowerRequirement = 0 },
369 { .version = 1,
370 .capabilityFlags = kIOPMRestartCapability,
371 .outputPowerCharacter = kIOPMRestart,
372 .inputPowerRequirement = RESTART_POWER },
373 { .version = 1,
374 .capabilityFlags = kIOPMSleepCapability,
375 .outputPowerCharacter = kIOPMSleep,
376 .inputPowerRequirement = SLEEP_POWER },
377 { .version = 1,
378 .capabilityFlags = kIOPMAOTCapability,
379 .outputPowerCharacter = kIOPMAOTPower,
380 .inputPowerRequirement = ON_POWER },
381 { .version = 1,
382 .capabilityFlags = kIOPMPowerOn,
383 .outputPowerCharacter = kIOPMPowerOn,
384 .inputPowerRequirement = ON_POWER },
385 };
386
387 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
388 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
389 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
390 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
391 #define kIOPMRootDomainWakeTypeUser "User"
392 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
393 #define kIOPMRootDomainWakeTypeNetwork "Network"
394 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
395 #define kIOPMRootDomainWakeTypeNotification "Notification"
396 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
397
398 // Special interest that entitles the interested client from receiving
399 // all system messages. Only used by powerd.
400 //
401 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
402
403 // Entitlement required for root domain clients
404 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
405
406 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
407 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
408
409 /*
410 * Aggressiveness
411 */
412 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
413 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
414
415 #define kAggressivesMinValue 1
416
417 const char *
getAggressivenessTypeString(uint32_t type)418 getAggressivenessTypeString( uint32_t type )
419 {
420 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
421
422 static const IONamedValue aggressivenessTypes[] = {
423 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ),
424 AGGRESSIVENESS_TYPE( kPMMinutesToDim ),
425 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ),
426 AGGRESSIVENESS_TYPE( kPMMinutesToSleep ),
427 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ),
428 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ),
429 AGGRESSIVENESS_TYPE( kPMPowerSource),
430 AGGRESSIVENESS_TYPE( kPMMotionSensor ),
431 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ),
432 { 0, NULL }
433 };
434 return IOFindNameForValue(type, aggressivenessTypes);
435 }
436
437 enum {
438 kAggressivesStateBusy = 0x01,
439 kAggressivesStateQuickSpindown = 0x02
440 };
441
442 struct AggressivesRecord {
443 uint32_t flags;
444 uint32_t type;
445 uint32_t value;
446 };
447
448 struct AggressivesRequest {
449 queue_chain_t chain;
450 uint32_t options;
451 uint32_t dataType;
452 union {
453 OSSharedPtr<IOService> service;
454 AggressivesRecord record;
455 } data;
456 };
457
458 enum {
459 kAggressivesRequestTypeService = 1,
460 kAggressivesRequestTypeRecord
461 };
462
463 enum {
464 kAggressivesOptionSynchronous = 0x00000001,
465 kAggressivesOptionQuickSpindownEnable = 0x00000100,
466 kAggressivesOptionQuickSpindownDisable = 0x00000200,
467 kAggressivesOptionQuickSpindownMask = 0x00000300
468 };
469
470 enum {
471 kAggressivesRecordFlagModified = 0x00000001,
472 kAggressivesRecordFlagMinValue = 0x00000002
473 };
474
475 // System Sleep Preventers
476
477 enum {
478 kPMUserDisabledAllSleep = 1,
479 kPMSystemRestartBootingInProgress,
480 kPMConfigPreventSystemSleep,
481 kPMChildPreventSystemSleep,
482 kPMCPUAssertion,
483 kPMPCIUnsupported,
484 kPMDKNotReady,
485 };
486
487 const char *
getSystemSleepPreventerString(uint32_t preventer)488 getSystemSleepPreventerString( uint32_t preventer )
489 {
490 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
491 static const IONamedValue systemSleepPreventers[] = {
492 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ),
493 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ),
494 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ),
495 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ),
496 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ),
497 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ),
498 SYSTEM_SLEEP_PREVENTER( kPMDKNotReady ),
499 { 0, NULL }
500 };
501 return IOFindNameForValue(preventer, systemSleepPreventers);
502 }
503
504 // gDarkWakeFlags
505 enum {
506 kDarkWakeFlagPromotionNone = 0x0000,
507 kDarkWakeFlagPromotionEarly = 0x0001, // promote before gfx clamp
508 kDarkWakeFlagPromotionLate = 0x0002, // promote after gfx clamp
509 kDarkWakeFlagPromotionMask = 0x0003,
510 kDarkWakeFlagAlarmIsDark = 0x0100,
511 kDarkWakeFlagAudioNotSuppressed = 0x0200,
512 kDarkWakeFlagUserWakeWorkaround = 0x1000
513 };
514
515 // gClamshellFlags
516 // The workaround for 9157444 is enabled at compile time using the
517 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below.
518 enum {
519 kClamshell_WAR_38378787 = 0x00000001,
520 kClamshell_WAR_47715679 = 0x00000002,
521 kClamshell_WAR_58009435 = 0x00000004
522 };
523
524 // acceptSystemWakeEvents()
525 enum {
526 kAcceptSystemWakeEvents_Disable = 0,
527 kAcceptSystemWakeEvents_Enable,
528 kAcceptSystemWakeEvents_Reenable
529 };
530
531 static IOPMrootDomain * gRootDomain;
532 static IORootParent * gPatriarch;
533 static IONotifier * gSysPowerDownNotifier = NULL;
534 static UInt32 gSleepOrShutdownPending = 0;
535 static UInt32 gWillShutdown = 0;
536 static UInt32 gPagingOff = 0;
537 static UInt32 gSleepWakeUUIDIsSet = false;
538 static uint32_t gAggressivesState = 0;
539 uint32_t gHaltTimeMaxLog;
540 uint32_t gHaltTimeMaxPanic;
541 IOLock * gHaltLogLock;
542 static char * gHaltLog;
543 enum { kHaltLogSize = 2048 };
544 static size_t gHaltLogPos;
545 static uint64_t gHaltStartTime;
546 static char gKextNameBuf[64];
547 static size_t gKextNamePos;
548 static bool gKextNameEnd;
549
550 uuid_string_t bootsessionuuid_string;
551
552 #if defined(XNU_TARGET_OS_OSX)
553 #if DISPLAY_WRANGLER_PRESENT
554 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionNone;
555 #elif defined(__arm64__)
556 // Enable temporary full wake promotion workarounds
557 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
558 #else
559 // Enable full wake promotion workarounds
560 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
561 #endif
562 #else /* !defined(XNU_TARGET_OS_OSX) */
563 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionEarly;
564 #endif /* !defined(XNU_TARGET_OS_OSX) */
565
566 static uint32_t gNoIdleFlag = 0;
567 static uint32_t gSleepDisabledFlag = 0;
568 static uint32_t gSwdPanic = 1;
569 static uint32_t gSwdSleepTimeout = 0;
570 static uint32_t gSwdWakeTimeout = 0;
571 static uint32_t gSwdSleepWakeTimeout = 0;
572 static PMStatsStruct gPMStats;
573 #if DEVELOPMENT || DEBUG
574 static uint32_t swd_panic_phase;
575 #endif
576
577 static uint32_t gClamshellFlags = 0
578 #if defined(__i386__) || defined(__x86_64__)
579 | kClamshell_WAR_58009435
580 #endif
581 ;
582
583 #if HIBERNATION
584
585 #if defined(__arm64__)
586 static IOReturn
defaultSleepPolicyHandler(void * ctx,const IOPMSystemSleepPolicyVariables * vars,IOPMSystemSleepParameters * params)587 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params)
588 {
589 uint32_t sleepType = kIOPMSleepTypeDeepIdle;
590
591 assert(vars->signature == kIOPMSystemSleepPolicySignature);
592 assert(vars->version == kIOPMSystemSleepPolicyVersion);
593
594 // Hibernation enabled and either user forced hibernate or low battery sleep
595 if ((vars->hibernateMode & kIOHibernateModeOn) &&
596 (((vars->hibernateMode & kIOHibernateModeSleep) == 0) ||
597 (vars->sleepFactors & kIOPMSleepFactorBatteryLow))) {
598 sleepType = kIOPMSleepTypeHibernate;
599 }
600 params->version = kIOPMSystemSleepParametersVersion;
601 params->sleepType = sleepType;
602 return kIOReturnSuccess;
603 }
604 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = &defaultSleepPolicyHandler;
605 #else /* defined(__arm64__) */
606 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = NULL;
607 #endif /* defined(__arm64__) */
608
609 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
610 static void * gSleepPolicyTarget;
611 #endif
612
613 struct timeval gIOLastSleepTime;
614 struct timeval gIOLastWakeTime;
615 AbsoluteTime gIOLastWakeAbsTime;
616 AbsoluteTime gIOLastSleepAbsTime;
617
618 struct timeval gIOLastUserSleepTime;
619
620 static char gWakeReasonString[128];
621 static char gBootReasonString[80];
622 static char gShutdownReasonString[80];
623 static bool gWakeReasonSysctlRegistered = false;
624 static bool gBootReasonSysctlRegistered = false;
625 static bool gShutdownReasonSysctlRegistered = false;
626 static bool gWillShutdownSysctlRegistered = false;
627 static AbsoluteTime gUserActiveAbsTime;
628 static AbsoluteTime gUserInactiveAbsTime;
629
630 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
631 static bool gSpinDumpBufferFull = false;
632 #endif
633
634 z_stream swd_zs;
635 vm_offset_t swd_zs_zmem;
636 //size_t swd_zs_zsize;
637 size_t swd_zs_zoffset;
638 #if defined(__i386__) || defined(__x86_64__)
639 IOCPU *currentShutdownTarget = NULL;
640 #endif
641
642 static unsigned int gPMHaltBusyCount;
643 static unsigned int gPMHaltIdleCount;
644 static int gPMHaltDepth;
645 static uint32_t gPMHaltMessageType;
646 static IOLock * gPMHaltLock = NULL;
647 static OSSharedPtr<OSArray> gPMHaltArray;
648 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey;
649 static bool gPMQuiesced;
650
651 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
652 #define kCPUUnknownIndex 9999999
653 enum {
654 kInformAC = 0,
655 kInformLid = 1,
656 kInformableCount = 2
657 };
658
659 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut;
660 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel;
661 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow;
662 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt;
663 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow;
664
665 #define kBadPMFeatureID 0
666
667 /*
668 * PMSettingHandle
669 * Opaque handle passed to clients of registerPMSettingController()
670 */
671 class PMSettingHandle : public OSObject
672 {
673 OSDeclareFinalStructors( PMSettingHandle );
674 friend class PMSettingObject;
675
676 private:
677 PMSettingObject *pmso;
678 void free(void) APPLE_KEXT_OVERRIDE;
679 };
680
681 /*
682 * PMSettingObject
683 * Internal object to track each PM setting controller
684 */
685 class PMSettingObject : public OSObject
686 {
687 OSDeclareFinalStructors( PMSettingObject );
688 friend class IOPMrootDomain;
689
690 private:
691 queue_head_t calloutQueue;
692 thread_t waitThread;
693 IOPMrootDomain *parent;
694 PMSettingHandle *pmsh;
695 IOPMSettingControllerCallback func;
696 OSObject *target;
697 uintptr_t refcon;
698 OSDataAllocation<uint32_t> publishedFeatureID;
699 uint32_t settingCount;
700 bool disabled;
701
702 void free(void) APPLE_KEXT_OVERRIDE;
703
704 public:
705 static PMSettingObject *pmSettingObject(
706 IOPMrootDomain *parent_arg,
707 IOPMSettingControllerCallback handler_arg,
708 OSObject *target_arg,
709 uintptr_t refcon_arg,
710 uint32_t supportedPowerSources,
711 const OSSymbol *settings[],
712 OSObject **handle_obj);
713
714 IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
715 void clientHandleFreed(void);
716 };
717
718 struct PMSettingCallEntry {
719 queue_chain_t link;
720 thread_t thread;
721 };
722
723 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
724 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
725 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
726 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
727
728 /*
729 * PMTraceWorker
730 * Internal helper object for logging trace points to RTC
731 * IOPMrootDomain and only IOPMrootDomain should instantiate
732 * exactly one of these.
733 */
734
735 typedef void (*IOPMTracePointHandler)(
736 void * target, uint32_t code, uint32_t data );
737
738 class PMTraceWorker : public OSObject
739 {
740 OSDeclareDefaultStructors(PMTraceWorker);
741 public:
742 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
743
744 static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * );
745 void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
746 void tracePoint(uint8_t phase);
747 void traceDetail(uint32_t detail);
748 void traceComponentWakeProgress(uint32_t component, uint32_t data);
749 int recordTopLevelPCIDevice(IOService *);
750 void RTC_TRACE(void);
751 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
752
753 IOPMTracePointHandler tracePointHandler;
754 void * tracePointTarget;
755 uint64_t getPMStatusCode();
756 uint8_t getTracePhase();
757 uint32_t getTraceData();
758 private:
759 IOPMrootDomain *owner;
760 IOLock *pmTraceWorkerLock;
761 OSSharedPtr<OSArray> pciDeviceBitMappings;
762
763 uint8_t addedToRegistry;
764 uint8_t tracePhase;
765 uint32_t traceData32;
766 uint8_t loginWindowData;
767 uint8_t coreDisplayData;
768 uint8_t coreGraphicsData;
769 };
770
771 /*
772 * this should be treated as POD, as it's byte-copied around
773 * and we cannot rely on d'tor firing at the right time
774 */
775 struct PMAssertStruct {
776 IOPMDriverAssertionID id;
777 IOPMDriverAssertionType assertionBits;
778 uint64_t createdTime;
779 uint64_t modifiedTime;
780 const OSSymbol *ownerString;
781 IOService *ownerService;
782 uint64_t registryEntryID;
783 IOPMDriverAssertionLevel level;
784 uint64_t assertCPUStartTime;
785 uint64_t assertCPUDuration;
786 };
787 OSDefineValueObjectForDependentType(PMAssertStruct)
788
789 /*
790 * PMAssertionsTracker
791 * Tracks kernel and user space PM assertions
792 */
793 class PMAssertionsTracker : public OSObject
794 {
795 OSDeclareFinalStructors(PMAssertionsTracker);
796 public:
797 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * );
798
799 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
800 IOReturn releaseAssertion(IOPMDriverAssertionID);
801 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
802 IOReturn setUserAssertionLevels(IOPMDriverAssertionType);
803
804 OSSharedPtr<OSArray> copyAssertionsArray(void);
805 IOPMDriverAssertionType getActivatedAssertions(void);
806 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType);
807
808 IOReturn handleCreateAssertion(OSValueObject<PMAssertStruct> *);
809 IOReturn handleReleaseAssertion(IOPMDriverAssertionID);
810 IOReturn handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
811 IOReturn handleSetUserAssertionLevels(void * arg0);
812 void publishProperties(void);
813 void reportCPUBitAccounting(void);
814 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *);
815
816 private:
817 uint32_t tabulateProducerCount;
818 uint32_t tabulateConsumerCount;
819
820 uint64_t maxAssertCPUDuration;
821 uint64_t maxAssertCPUEntryId;
822
823 void tabulate(void);
824 void updateCPUBitAccounting(PMAssertStruct * assertStruct);
825
826 IOPMrootDomain *owner;
827 OSSharedPtr<OSArray> assertionsArray;
828 IOLock *assertionsArrayLock;
829 IOPMDriverAssertionID issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
830 IOPMDriverAssertionType assertionsKernel;
831 IOPMDriverAssertionType assertionsUser;
832 IOPMDriverAssertionType assertionsCombined;
833 };
834
835 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
836
837 /*
838 * PMHaltWorker
839 * Internal helper object for Shutdown/Restart notifications.
840 */
841 #define kPMHaltMaxWorkers 8
842 #define kPMHaltTimeoutMS 100
843
844 class PMHaltWorker : public OSObject
845 {
846 OSDeclareFinalStructors( PMHaltWorker );
847
848 public:
849 IOService * service;// service being worked on
850 AbsoluteTime startTime; // time when work started
851 int depth; // work on nubs at this PM-tree depth
852 int visits; // number of nodes visited (debug)
853 IOLock * lock;
854 bool timeout;// service took too long
855
856 static PMHaltWorker * worker( void );
857 static void main( void * arg, wait_result_t waitResult );
858 static void work( PMHaltWorker * me );
859 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
860 virtual void free( void ) APPLE_KEXT_OVERRIDE;
861 };
862
OSDefineMetaClassAndFinalStructors(PMHaltWorker,OSObject)863 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
864
865
866 #define super IOService
867 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
868
869 boolean_t
870 IOPMRootDomainGetWillShutdown(void)
871 {
872 return gWillShutdown != 0;
873 }
874
875 static void
IOPMRootDomainWillShutdown(void)876 IOPMRootDomainWillShutdown(void)
877 {
878 if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
879 IOService::willShutdown();
880 for (int i = 0; i < 100; i++) {
881 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
882 break;
883 }
884 IOSleep( 100 );
885 }
886 }
887 }
888
889 extern "C" IONotifier *
registerSleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)890 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
891 {
892 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
893 }
894
895 extern "C" IONotifier *
registerPrioritySleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)896 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
897 {
898 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
899 }
900
901 extern "C" IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon)902 acknowledgeSleepWakeNotification(void * PMrefcon)
903 {
904 return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
905 }
906
907 extern "C" IOReturn
vetoSleepWakeNotification(void * PMrefcon)908 vetoSleepWakeNotification(void * PMrefcon)
909 {
910 return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
911 }
912
913 extern "C" IOReturn
rootDomainRestart(void)914 rootDomainRestart( void )
915 {
916 return gRootDomain->restartSystem();
917 }
918
919 extern "C" IOReturn
rootDomainShutdown(void)920 rootDomainShutdown( void )
921 {
922 return gRootDomain->shutdownSystem();
923 }
924
925 static void
halt_log_putc(char c)926 halt_log_putc(char c)
927 {
928 if (gHaltLogPos >= (kHaltLogSize - 2)) {
929 return;
930 }
931 gHaltLog[gHaltLogPos++] = c;
932 }
933
934 extern "C" void
935 _doprnt_log(const char *fmt,
936 va_list *argp,
937 void (*putc)(char),
938 int radix);
939
940 static int
halt_log(const char * fmt,...)941 halt_log(const char *fmt, ...)
942 {
943 va_list listp;
944
945 va_start(listp, fmt);
946 _doprnt_log(fmt, &listp, &halt_log_putc, 16);
947 va_end(listp);
948
949 return 0;
950 }
951
952 extern "C" void
halt_log_enter(const char * what,const void * pc,uint64_t time)953 halt_log_enter(const char * what, const void * pc, uint64_t time)
954 {
955 uint64_t nano, millis;
956
957 if (!gHaltLog) {
958 return;
959 }
960 absolutetime_to_nanoseconds(time, &nano);
961 millis = nano / NSEC_PER_MSEC;
962 if (millis < 100) {
963 return;
964 }
965
966 IOLockLock(gHaltLogLock);
967 if (pc) {
968 halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
969 OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
970 OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
971 } else {
972 halt_log("%s: %qd ms\n", what, millis);
973 }
974
975 gHaltLog[gHaltLogPos] = 0;
976 IOLockUnlock(gHaltLogLock);
977 }
978
979 extern uint32_t gFSState;
980
981 extern "C" void
IOSystemShutdownNotification(int howto,int stage)982 IOSystemShutdownNotification(int howto, int stage)
983 {
984 uint64_t startTime;
985
986 if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
987 #if defined(XNU_TARGET_OS_OSX)
988 uint64_t nano, millis;
989 startTime = mach_absolute_time();
990 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
991 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
992 millis = nano / NSEC_PER_MSEC;
993 if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
994 printf("waitQuiet() for unmount %qd ms\n", millis);
995 }
996 #endif /* defined(XNU_TARGET_OS_OSX) */
997 return;
998 }
999
1000 if (kIOSystemShutdownNotificationTerminateDEXTs == stage) {
1001 uint64_t nano, millis;
1002 startTime = mach_absolute_time();
1003 IOServicePH::systemHalt(howto);
1004 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
1005 millis = nano / NSEC_PER_MSEC;
1006 if (true || (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog))) {
1007 printf("IOServicePH::systemHalt took %qd ms\n", millis);
1008 }
1009 return;
1010 }
1011
1012 assert(kIOSystemShutdownNotificationStageProcessExit == stage);
1013
1014 IOLockLock(gHaltLogLock);
1015 if (!gHaltLog) {
1016 gHaltLog = IONewData(char, (vm_size_t)kHaltLogSize);
1017 gHaltStartTime = mach_absolute_time();
1018 if (gHaltLog) {
1019 halt_log_putc('\n');
1020 }
1021 }
1022 IOLockUnlock(gHaltLogLock);
1023
1024 startTime = mach_absolute_time();
1025 IOPMRootDomainWillShutdown();
1026 halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
1027 #if HIBERNATION
1028 startTime = mach_absolute_time();
1029 IOHibernateSystemPostWake(true);
1030 halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
1031 #endif
1032 if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1033 gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1034 }
1035 }
1036
1037 extern "C" int sync_internal(void);
1038
1039 /*
1040 * A device is always in the highest power state which satisfies its driver,
1041 * its policy-maker, and any power children it has, but within the constraint
1042 * of the power state provided by its parent. The driver expresses its desire by
1043 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
1044 * changePowerStateToPriv(), and the children express their desires by calling
1045 * requestPowerDomainState().
1046 *
1047 * The Root Power Domain owns the policy for idle and demand sleep for the system.
1048 * It is a power-managed IOService just like the others in the system.
1049 * It implements several power states which map to what we see as Sleep and On.
1050 *
1051 * The sleep policy is as follows:
1052 * 1. Sleep is prevented if the case is open so that nobody will think the machine
1053 * is off and plug/unplug cards.
1054 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1055 * 3. System cannot Sleep if some object in the tree is in a power state marked
1056 * kIOPMPreventSystemSleep.
1057 *
1058 * These three conditions are enforced using the "driver clamp" by calling
1059 * changePowerStateTo(). For example, if the case is opened,
1060 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
1061 * of the desires of the children of the root or the state of the other clamp.
1062 *
1063 * Demand Sleep is initiated by pressing the front panel power button, closing
1064 * the clamshell, or selecting the menu item. In this case the root's parent
1065 * actually initiates the power state change so that the root domain has no
1066 * choice and does not give applications the opportunity to veto the change.
1067 *
1068 * Idle Sleep occurs if no objects in the tree are in a state marked
1069 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
1070 * the root on, so it sets the "policy-maker clamp" by calling
1071 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1072 * This timer is set for the difference between the sleep timeout slider and the
1073 * display dim timeout slider. When the timer expires, it releases its clamp and
1074 * now nothing is holding it awake, so it falls asleep.
1075 *
1076 * Demand sleep is prevented when the system is booting. When preferences are
1077 * transmitted by the loginwindow at the end of boot, a flag is cleared,
1078 * and this allows subsequent Demand Sleep.
1079 */
1080
1081 //******************************************************************************
1082
1083 IOPMrootDomain *
construct(void)1084 IOPMrootDomain::construct( void )
1085 {
1086 IOPMrootDomain *root;
1087
1088 root = new IOPMrootDomain;
1089 if (root) {
1090 root->init();
1091 }
1092
1093 return root;
1094 }
1095
1096 //******************************************************************************
1097 // updateConsoleUsersCallout
1098 //
1099 //******************************************************************************
1100
1101 static void
updateConsoleUsersCallout(thread_call_param_t p0,thread_call_param_t p1)1102 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1103 {
1104 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1105 rootDomain->updateConsoleUsers();
1106 }
1107
1108 void
updateConsoleUsers(void)1109 IOPMrootDomain::updateConsoleUsers(void)
1110 {
1111 IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1112 updateTasksSuspend(kTasksSuspendUnsuspended, kTasksSuspendNoChange);
1113 }
1114
1115 bool
updateTasksSuspend(int newTasksSuspended,int newAOTTasksSuspended)1116 IOPMrootDomain::updateTasksSuspend(int newTasksSuspended, int newAOTTasksSuspended)
1117 {
1118 bool newSuspend;
1119
1120 WAKEEVENT_LOCK();
1121 if (newTasksSuspended != kTasksSuspendNoChange) {
1122 tasksSuspended = (newTasksSuspended != kTasksSuspendUnsuspended);
1123 }
1124 if (newAOTTasksSuspended != kTasksSuspendNoChange) {
1125 _aotTasksSuspended = (newAOTTasksSuspended != kTasksSuspendUnsuspended);
1126 }
1127 newSuspend = (tasksSuspended || _aotTasksSuspended);
1128 if (newSuspend == tasksSuspendState) {
1129 WAKEEVENT_UNLOCK();
1130 return false;
1131 }
1132 tasksSuspendState = newSuspend;
1133 WAKEEVENT_UNLOCK();
1134 tasks_system_suspend(newSuspend);
1135 return true;
1136 }
1137
1138 //******************************************************************************
1139
1140 static void
disk_sync_callout(thread_call_param_t p0,thread_call_param_t p1)1141 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1142 {
1143 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1144 uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
1145 uint32_t powerState = rootDomain->getPowerState();
1146
1147 DLOG("disk_sync_callout ps=%u\n", powerState);
1148
1149 if (ON_STATE == powerState) {
1150 sync_internal();
1151
1152 #if HIBERNATION
1153 // Block sleep until trim issued on previous wake path is completed.
1154 IOHibernateSystemPostWake(true);
1155 #endif
1156 }
1157 #if HIBERNATION
1158 else {
1159 IOHibernateSystemPostWake(false);
1160
1161 rootDomain->sleepWakeDebugSaveSpinDumpFile();
1162 }
1163 #endif
1164
1165 rootDomain->allowPowerChange(notifyRef);
1166 DLOG("disk_sync_callout finish\n");
1167 }
1168
1169 //******************************************************************************
1170 static UInt32
computeDeltaTimeMS(const AbsoluteTime * startTime,AbsoluteTime * elapsedTime)1171 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1172 {
1173 AbsoluteTime endTime;
1174 UInt64 nano = 0;
1175
1176 clock_get_uptime(&endTime);
1177 if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1178 *elapsedTime = 0;
1179 } else {
1180 SUB_ABSOLUTETIME(&endTime, startTime);
1181 absolutetime_to_nanoseconds(endTime, &nano);
1182 *elapsedTime = endTime;
1183 }
1184
1185 return (UInt32)(nano / NSEC_PER_MSEC);
1186 }
1187
1188 //******************************************************************************
1189
1190 static int
1191 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1192 {
1193 struct timeval *swt = (struct timeval *)arg1;
1194 struct proc *p = req->p;
1195
1196 if (p == kernproc) {
1197 return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
1198 } else if (proc_is64bit(p)) {
1199 struct user64_timeval t = {};
1200 t.tv_sec = swt->tv_sec;
1201 t.tv_usec = swt->tv_usec;
1202 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1203 } else {
1204 struct user32_timeval t = {};
1205 t.tv_sec = (typeof(t.tv_sec))swt->tv_sec;
1206 t.tv_usec = swt->tv_usec;
1207 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1208 }
1209 }
1210
1211 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1212 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1213 &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1214
1215 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1216 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1217 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1218
1219 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
1220 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
1221 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
1222 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
1223
1224 static int
1225 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1226 {
1227 int new_value, changed, error;
1228
1229 if (!gWillShutdownSysctlRegistered) {
1230 return ENOENT;
1231 }
1232
1233 error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1234 if (changed) {
1235 if (!gWillShutdown && (new_value == 1)) {
1236 IOPMRootDomainWillShutdown();
1237 } else {
1238 error = EINVAL;
1239 }
1240 }
1241 return error;
1242 }
1243
1244 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1245 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1246 NULL, 0, sysctl_willshutdown, "I", "");
1247
1248 #if defined(XNU_TARGET_OS_OSX)
1249
1250 static int
sysctl_progressmeterenable(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1251 sysctl_progressmeterenable
1252 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1253 {
1254 int error;
1255 int new_value, changed;
1256
1257 error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1258
1259 if (changed) {
1260 vc_enable_progressmeter(new_value);
1261 }
1262
1263 return error;
1264 }
1265
1266 static int
sysctl_progressmeter(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1267 sysctl_progressmeter
1268 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1269 {
1270 int error;
1271 int new_value, changed;
1272
1273 error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1274
1275 if (changed) {
1276 vc_set_progressmeter(new_value);
1277 }
1278
1279 return error;
1280 }
1281
1282 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1283 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1284 NULL, 0, sysctl_progressmeterenable, "I", "");
1285
1286 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1287 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1288 NULL, 0, sysctl_progressmeter, "I", "");
1289
1290 #endif /* defined(XNU_TARGET_OS_OSX) */
1291
1292
1293
1294 static int
sysctl_consoleoptions(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1295 sysctl_consoleoptions
1296 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1297 {
1298 int error, changed;
1299 uint32_t new_value;
1300
1301 error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1302
1303 if (changed) {
1304 vc_user_options.options = new_value;
1305 }
1306
1307 return error;
1308 }
1309
1310 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1311 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1312 NULL, 0, sysctl_consoleoptions, "I", "");
1313
1314
1315 static int
1316 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1317 {
1318 return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1319 }
1320
1321 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1322 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1323 NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1324
1325
1326 static int
1327 sysctl_wakereason SYSCTL_HANDLER_ARGS
1328 {
1329 char wr[sizeof(gWakeReasonString)];
1330
1331 wr[0] = '\0';
1332 if (gRootDomain && gWakeReasonSysctlRegistered) {
1333 gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1334 } else {
1335 return ENOENT;
1336 }
1337
1338 return sysctl_io_string(req, wr, 0, 0, NULL);
1339 }
1340
1341 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1342 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1343 NULL, 0, sysctl_wakereason, "A", "wakereason");
1344
1345 static int
1346 sysctl_bootreason SYSCTL_HANDLER_ARGS
1347 {
1348 if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) {
1349 return ENOENT;
1350 }
1351
1352 return sysctl_io_string(req, gBootReasonString, 0, 0, NULL);
1353 }
1354
1355 SYSCTL_PROC(_kern, OID_AUTO, bootreason,
1356 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1357 NULL, 0, sysctl_bootreason, "A", "");
1358
1359 static int
1360 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1361 {
1362 char sr[sizeof(gShutdownReasonString)];
1363
1364 sr[0] = '\0';
1365 if (gRootDomain && gShutdownReasonSysctlRegistered) {
1366 gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1367 } else {
1368 return ENOENT;
1369 }
1370
1371 return sysctl_io_string(req, sr, 0, 0, NULL);
1372 }
1373
1374 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1375 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1376 NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1377
1378 static int
1379 sysctl_targettype SYSCTL_HANDLER_ARGS
1380 {
1381 IOService * root;
1382 OSSharedPtr<OSObject> obj;
1383 OSData * data;
1384 char tt[32];
1385
1386 tt[0] = '\0';
1387 root = IOService::getServiceRoot();
1388 if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1389 if ((data = OSDynamicCast(OSData, obj.get()))) {
1390 strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1391 }
1392 }
1393 return sysctl_io_string(req, tt, 0, 0, NULL);
1394 }
1395
1396 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1397 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1398 NULL, 0, sysctl_targettype, "A", "targettype");
1399
1400 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1401 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1402 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1403 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1404 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1405 #if DEVELOPMENT || DEBUG
1406 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
1407 #if defined(XNU_TARGET_OS_OSX)
1408 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, "");
1409 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1410 #endif /* defined(XNU_TARGET_OS_OSX) */
1411 #endif /* DEVELOPMENT || DEBUG */
1412
1413 //******************************************************************************
1414 // AOT
1415
1416 static int
1417 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1418 {
1419 if (NULL == gRootDomain) {
1420 return ENOENT;
1421 }
1422 if (NULL == gRootDomain->_aotMetrics) {
1423 IOPMAOTMetrics nullMetrics = {};
1424 return sysctl_io_opaque(req, &nullMetrics, sizeof(IOPMAOTMetrics), NULL);
1425 }
1426 return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1427 }
1428
1429 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
1430 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1431 NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
1432
1433
1434 static int
update_aotmode(uint32_t mode)1435 update_aotmode(uint32_t mode)
1436 {
1437 int result;
1438
1439 if (!gIOPMWorkLoop) {
1440 return ENOENT;
1441 }
1442 result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1443 unsigned int oldCount;
1444
1445 if (mode) {
1446 gRootDomain->initAOTMetrics();
1447 }
1448
1449 oldCount = gRootDomain->idleSleepPreventersCount();
1450 gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1451 gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1452 return 0;
1453 });
1454 return result;
1455 }
1456
1457 static int
sysctl_aotmodebits(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1458 sysctl_aotmodebits
1459 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1460 {
1461 int error, changed;
1462 uint32_t new_value;
1463
1464 if (NULL == gRootDomain) {
1465 return ENOENT;
1466 }
1467 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1468 if (changed && gIOPMWorkLoop) {
1469 error = update_aotmode(new_value);
1470 }
1471
1472 return error;
1473 }
1474
1475 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1476 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1477 NULL, 0, sysctl_aotmodebits, "I", "");
1478
1479 static int
sysctl_aotmode(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1480 sysctl_aotmode
1481 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1482 {
1483 int error, changed;
1484 uint32_t new_value;
1485
1486 if (NULL == gRootDomain) {
1487 return ENOENT;
1488 }
1489 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1490 if (changed && gIOPMWorkLoop) {
1491 if (new_value) {
1492 new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1493 }
1494 error = update_aotmode(new_value);
1495 }
1496
1497 return error;
1498 }
1499
1500 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
1501 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1502 NULL, 0, sysctl_aotmode, "I", "");
1503
1504 //******************************************************************************
1505
1506 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey;
1507 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey;
1508 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey;
1509 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey;
1510 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey;
1511 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey;
1512 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey;
1513 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey;
1514 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey;
1515 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey;
1516 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey;
1517 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey;
1518
1519 //******************************************************************************
1520 // start
1521 //
1522 //******************************************************************************
1523
1524 #define kRootDomainSettingsCount 20
1525 #define kRootDomainNoPublishSettingsCount 4
1526
1527 bool
start(IOService * nub)1528 IOPMrootDomain::start( IOService * nub )
1529 {
1530 OSSharedPtr<OSIterator> psIterator;
1531 OSSharedPtr<OSDictionary> tmpDict;
1532
1533 super::start(nub);
1534
1535 gRootDomain = this;
1536 gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1537 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1538 gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
1539 gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
1540 gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1541 gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
1542 gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1543 gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1544 gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1545 gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1546 gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1547 gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey);
1548
1549 gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1550 gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1551 gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1552 gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1553 gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1554
1555 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1556 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1557 gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1558
1559 OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1560 {
1561 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1562 gIOPMSettingAutoWakeSecondsKey,
1563 gIOPMSettingAutoPowerSecondsKey,
1564 gIOPMSettingAutoWakeCalendarKey,
1565 gIOPMSettingAutoPowerCalendarKey,
1566 gIOPMSettingDebugWakeRelativeKey,
1567 gIOPMSettingDebugPowerRelativeKey,
1568 OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1569 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1570 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1571 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1572 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1573 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1574 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1575 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1576 OSSymbol::withCString(kIOPMStateConsoleShutdown),
1577 OSSymbol::withCString(kIOPMSettingProModeControl),
1578 OSSymbol::withCString(kIOPMSettingProModeDefer),
1579 gIOPMSettingSilentRunningKey,
1580 gIOPMSettingLowLatencyAudioModeKey,
1581 };
1582
1583 OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1584 {
1585 OSSymbol::withCString(kIOPMSettingProModeControl),
1586 OSSymbol::withCString(kIOPMSettingProModeDefer),
1587 gIOPMSettingSilentRunningKey,
1588 gIOPMSettingLowLatencyAudioModeKey,
1589 };
1590
1591 #if DEVELOPMENT || DEBUG
1592 #if defined(XNU_TARGET_OS_OSX)
1593 PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1594 PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags));
1595 #endif /* defined(XNU_TARGET_OS_OSX) */
1596 #endif /* DEVELOPMENT || DEBUG */
1597
1598 PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1599 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1600 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1601 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1602 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1603 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1604
1605 // read noidle setting from Device Tree
1606 if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
1607 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
1608 }
1609
1610 queue_init(&aggressivesQueue);
1611 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1612 aggressivesData = OSData::withCapacity(
1613 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1614
1615 featuresDictLock = IOLockAlloc();
1616 settingsCtrlLock = IOLockAlloc();
1617 wakeEventLock = IOLockAlloc();
1618 gHaltLogLock = IOLockAlloc();
1619 setPMRootDomain(this);
1620
1621 extraSleepTimer = thread_call_allocate(
1622 idleSleepTimerExpired,
1623 (thread_call_param_t) this);
1624
1625 powerButtonDown = thread_call_allocate(
1626 powerButtonDownCallout,
1627 (thread_call_param_t) this);
1628
1629 powerButtonUp = thread_call_allocate(
1630 powerButtonUpCallout,
1631 (thread_call_param_t) this);
1632
1633 diskSyncCalloutEntry = thread_call_allocate(
1634 &disk_sync_callout,
1635 (thread_call_param_t) this);
1636 updateConsoleUsersEntry = thread_call_allocate(
1637 &updateConsoleUsersCallout,
1638 (thread_call_param_t) this);
1639
1640 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1641 fullWakeThreadCall = thread_call_allocate_with_options(
1642 OSMemberFunctionCast(thread_call_func_t, this,
1643 &IOPMrootDomain::fullWakeDelayedWork),
1644 (thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL,
1645 THREAD_CALL_OPTIONS_ONCE);
1646 #endif
1647
1648 setProperty(kIOSleepSupportedKey, true);
1649
1650 bzero(&gPMStats, sizeof(gPMStats));
1651
1652 pmTracer = PMTraceWorker::tracer(this);
1653
1654 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1655
1656 userDisabledAllSleep = false;
1657 systemBooting = true;
1658 idleSleepEnabled = false;
1659 idleSleepRevertible = true;
1660 sleepSlider = 0;
1661 idleSleepTimerPending = false;
1662 wrangler = NULL;
1663 clamshellClosed = false;
1664 clamshellExists = false;
1665 #if DISPLAY_WRANGLER_PRESENT
1666 clamshellDisabled = true;
1667 #else
1668 clamshellDisabled = false;
1669 #endif
1670 clamshellIgnoreClose = false;
1671 acAdaptorConnected = true;
1672 clamshellSleepDisableMask = 0;
1673 gWakeReasonString[0] = '\0';
1674
1675 // Initialize to user active.
1676 // Will never transition to user inactive w/o wrangler.
1677 fullWakeReason = kFullWakeReasonLocalUser;
1678 userIsActive = userWasActive = true;
1679 clock_get_uptime(&gUserActiveAbsTime);
1680 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
1681
1682 // Set the default system capabilities at boot.
1683 _currentCapability = kIOPMSystemCapabilityCPU |
1684 kIOPMSystemCapabilityGraphics |
1685 kIOPMSystemCapabilityAudio |
1686 kIOPMSystemCapabilityNetwork;
1687
1688 _pendingCapability = _currentCapability;
1689 _desiredCapability = _currentCapability;
1690 _highestCapability = _currentCapability;
1691 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1692
1693 queuedSleepWakeUUIDString = NULL;
1694 initializeBootSessionUUID();
1695 pmStatsAppResponses = OSArray::withCapacity(5);
1696 _statsNameKey = OSSymbol::withCString(kIOPMStatsNameKey);
1697 _statsPIDKey = OSSymbol::withCString(kIOPMStatsPIDKey);
1698 _statsTimeMSKey = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1699 _statsResponseTypeKey = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1700 _statsMessageTypeKey = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1701 _statsPowerCapsKey = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1702 assertOnWakeSecs = -1;// Invalid value to prevent updates
1703
1704 pmStatsLock = IOLockAlloc();
1705 idxPMCPUClamshell = kCPUUnknownIndex;
1706 idxPMCPULimitedPower = kCPUUnknownIndex;
1707
1708 tmpDict = OSDictionary::withCapacity(1);
1709 setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1710
1711 // Set a default "SystemPowerProfileOverrideDict" for platform
1712 // drivers without any overrides.
1713 if (!propertyExists(kIOPMSystemDefaultOverrideKey)) {
1714 tmpDict = OSDictionary::withCapacity(1);
1715 setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get());
1716 }
1717
1718 settingsCallbacks = OSDictionary::withCapacity(1);
1719
1720 // Create a list of the valid PM settings that we'll relay to
1721 // interested clients in setProperties() => setPMSetting()
1722 allowedPMSettings = OSArray::withObjects(
1723 (const OSObject **)settingsArr,
1724 kRootDomainSettingsCount,
1725 0);
1726
1727 // List of PM settings that should not automatically publish itself
1728 // as a feature when registered by a listener.
1729 noPublishPMSettings = OSArray::withObjects(
1730 (const OSObject **)noPublishSettingsArr,
1731 kRootDomainNoPublishSettingsCount,
1732 0);
1733
1734 fPMSettingsDict = OSDictionary::withCapacity(5);
1735 preventIdleSleepList = OSSet::withCapacity(8);
1736 preventSystemSleepList = OSSet::withCapacity(2);
1737
1738 PMinit(); // creates gIOPMWorkLoop
1739 gIOPMWorkLoop = getIOPMWorkloop();
1740
1741 // Create IOPMPowerStateQueue used to queue external power
1742 // events, and to handle those events on the PM work loop.
1743 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1744 this, OSMemberFunctionCast(IOEventSource::Action, this,
1745 &IOPMrootDomain::dispatchPowerEvent));
1746 gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1747
1748 _aotMode = 0;
1749 _aotTimerES = IOTimerEventSource::timerEventSource(this,
1750 OSMemberFunctionCast(IOTimerEventSource::Action,
1751 this, &IOPMrootDomain::aotEvaluate));
1752 gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1753
1754 // Avoid publishing service early so gIOPMWorkLoop is
1755 // guaranteed to be initialized by rootDomain.
1756 publishPMRootDomain();
1757
1758 // create our power parent
1759 gPatriarch = new IORootParent;
1760 gPatriarch->init();
1761 gPatriarch->attach(this);
1762 gPatriarch->start(this);
1763 gPatriarch->addPowerChild(this);
1764
1765 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1766 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1767
1768 // install power change handler
1769 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1770
1771 #if DISPLAY_WRANGLER_PRESENT
1772 wranglerIdleSettings = OSDictionary::withCapacity(1);
1773 OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1774
1775 if (wranglerIdleSettings && wranglerIdlePeriod) {
1776 wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1777 wranglerIdlePeriod.get());
1778 }
1779
1780 #endif /* DISPLAY_WRANGLER_PRESENT */
1781
1782 lowLatencyAudioNotifierDict = OSDictionary::withCapacity(2);
1783 lowLatencyAudioNotifyStateSym = OSSymbol::withCString("LowLatencyAudioNotifyState");
1784 lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1785 lowLatencyAudioNotifyStateVal = OSNumber::withNumber(0ull, 32);
1786 lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64);
1787
1788 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1789 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1790 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1791 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1792 }
1793
1794 OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1795 setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1796
1797 // IOBacklightDisplay can take a long time to load at boot, or it may
1798 // not load at all if you're booting with clamshell closed. We publish
1799 // 'DisplayDims' here redundantly to get it published early and at all.
1800 OSSharedPtr<OSDictionary> matching;
1801 matching = serviceMatching("IOPMPowerSource");
1802 psIterator = getMatchingServices(matching.get());
1803
1804 if (psIterator && psIterator->getNextObject()) {
1805 // There's at least one battery on the system, so we publish
1806 // 'DisplayDims' support for the LCD.
1807 publishFeature("DisplayDims");
1808 }
1809
1810 // read swd_panic boot-arg
1811 PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1812 gWillShutdownSysctlRegistered = true;
1813
1814 #if HIBERNATION
1815 IOHibernateSystemInit(this);
1816 #endif
1817
1818 registerService(); // let clients find us
1819
1820 return true;
1821 }
1822
1823 //******************************************************************************
1824 // setProperties
1825 //
1826 // Receive a setProperty call
1827 // The "System Boot" property means the system is completely booted.
1828 //******************************************************************************
1829
1830 IOReturn
setProperties(OSObject * props_obj)1831 IOPMrootDomain::setProperties( OSObject * props_obj )
1832 {
1833 IOReturn return_value = kIOReturnSuccess;
1834 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
1835 OSBoolean *b = NULL;
1836 OSNumber *n = NULL;
1837 const OSSymbol *key = NULL;
1838 OSObject *obj = NULL;
1839 OSSharedPtr<OSCollectionIterator> iter;
1840
1841 if (!dict) {
1842 return kIOReturnBadArgument;
1843 }
1844
1845 bool clientEntitled = false;
1846 {
1847 OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1848 clientEntitled = (obj == kOSBooleanTrue);
1849 }
1850
1851 if (!clientEntitled) {
1852 const char * errorSuffix = NULL;
1853
1854 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1855 // That API can set 6 possible keys that are checked below.
1856 if ((dict->getCount() == 1) &&
1857 (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) ||
1858 dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) ||
1859 dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) ||
1860 dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) ||
1861 dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) ||
1862 dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) {
1863 return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
1864 if (return_value != kIOReturnSuccess) {
1865 errorSuffix = "privileged";
1866 }
1867 } else {
1868 return_value = kIOReturnNotPermitted;
1869 errorSuffix = "entitled";
1870 }
1871
1872 if (return_value != kIOReturnSuccess) {
1873 OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain);
1874 DLOG("%s failed, process %s is not %s\n", __func__,
1875 procName ? procName->getCStringNoCopy() : "", errorSuffix);
1876 return return_value;
1877 }
1878 }
1879
1880 OSSharedPtr<const OSSymbol> publish_simulated_battery_string = OSSymbol::withCString("SoftwareSimulatedBatteries");
1881 OSSharedPtr<const OSSymbol> boot_complete_string = OSSymbol::withCString("System Boot Complete");
1882 OSSharedPtr<const OSSymbol> sys_shutdown_string = OSSymbol::withCString("System Shutdown");
1883 OSSharedPtr<const OSSymbol> stall_halt_string = OSSymbol::withCString("StallSystemAtHalt");
1884 OSSharedPtr<const OSSymbol> battery_warning_disabled_string = OSSymbol::withCString("BatteryWarningsDisabled");
1885 OSSharedPtr<const OSSymbol> idle_seconds_string = OSSymbol::withCString("System Idle Seconds");
1886 OSSharedPtr<const OSSymbol> idle_milliseconds_string = OSSymbol::withCString("System Idle Milliseconds");
1887 OSSharedPtr<const OSSymbol> sleepdisabled_string = OSSymbol::withCString("SleepDisabled");
1888 OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1889 OSSharedPtr<const OSSymbol> loginwindow_progress_string = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1890 OSSharedPtr<const OSSymbol> coredisplay_progress_string = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1891 OSSharedPtr<const OSSymbol> coregraphics_progress_string = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1892 #if DEBUG || DEVELOPMENT
1893 OSSharedPtr<const OSSymbol> clamshell_close_string = OSSymbol::withCString("IOPMTestClamshellClose");
1894 OSSharedPtr<const OSSymbol> clamshell_open_string = OSSymbol::withCString("IOPMTestClamshellOpen");
1895 OSSharedPtr<const OSSymbol> ac_detach_string = OSSymbol::withCString("IOPMTestACDetach");
1896 OSSharedPtr<const OSSymbol> ac_attach_string = OSSymbol::withCString("IOPMTestACAttach");
1897 OSSharedPtr<const OSSymbol> desktopmode_set_string = OSSymbol::withCString("IOPMTestDesktopModeSet");
1898 OSSharedPtr<const OSSymbol> desktopmode_remove_string = OSSymbol::withCString("IOPMTestDesktopModeRemove");
1899 #endif
1900
1901 #if HIBERNATION
1902 OSSharedPtr<const OSSymbol> hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey);
1903 OSSharedPtr<const OSSymbol> hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey);
1904 OSSharedPtr<const OSSymbol> hibernatefilemin_string = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
1905 OSSharedPtr<const OSSymbol> hibernatefilemax_string = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
1906 OSSharedPtr<const OSSymbol> hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey);
1907 OSSharedPtr<const OSSymbol> hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey);
1908 #endif
1909
1910 iter = OSCollectionIterator::withCollection(dict);
1911 if (!iter) {
1912 return_value = kIOReturnNoMemory;
1913 goto exit;
1914 }
1915
1916 while ((key = (const OSSymbol *) iter->getNextObject()) &&
1917 (obj = dict->getObject(key))) {
1918 if (key->isEqualTo(publish_simulated_battery_string.get())) {
1919 if (OSDynamicCast(OSBoolean, obj)) {
1920 publishResource(key, kOSBooleanTrue);
1921 }
1922 } else if (key->isEqualTo(idle_seconds_string.get())) {
1923 if ((n = OSDynamicCast(OSNumber, obj))) {
1924 setProperty(key, n);
1925 idleMilliSeconds = n->unsigned32BitValue() * 1000;
1926 }
1927 } else if (key->isEqualTo(idle_milliseconds_string.get())) {
1928 if ((n = OSDynamicCast(OSNumber, obj))) {
1929 setProperty(key, n);
1930 idleMilliSeconds = n->unsigned32BitValue();
1931 }
1932 } else if (key->isEqualTo(boot_complete_string.get())) {
1933 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
1934 } else if (key->isEqualTo(sys_shutdown_string.get())) {
1935 if ((b = OSDynamicCast(OSBoolean, obj))) {
1936 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
1937 }
1938 } else if (key->isEqualTo(battery_warning_disabled_string.get())) {
1939 setProperty(key, obj);
1940 }
1941 #if HIBERNATION
1942 else if (key->isEqualTo(hibernatemode_string.get()) ||
1943 key->isEqualTo(hibernatefilemin_string.get()) ||
1944 key->isEqualTo(hibernatefilemax_string.get()) ||
1945 key->isEqualTo(hibernatefreeratio_string.get()) ||
1946 key->isEqualTo(hibernatefreetime_string.get())) {
1947 if ((n = OSDynamicCast(OSNumber, obj))) {
1948 setProperty(key, n);
1949 }
1950 } else if (key->isEqualTo(hibernatefile_string.get())) {
1951 OSString * str = OSDynamicCast(OSString, obj);
1952 if (str) {
1953 setProperty(key, str);
1954 }
1955 }
1956 #endif
1957 else if (key->isEqualTo(sleepdisabled_string.get())) {
1958 if ((b = OSDynamicCast(OSBoolean, obj))) {
1959 setProperty(key, b);
1960 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1961 }
1962 } else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
1963 obj->retain();
1964 pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
1965 } else if (key->isEqualTo(loginwindow_progress_string.get())) {
1966 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1967 uint32_t data = n->unsigned32BitValue();
1968 pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
1969 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
1970 }
1971 } else if (key->isEqualTo(coredisplay_progress_string.get())) {
1972 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1973 uint32_t data = n->unsigned32BitValue();
1974 pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
1975 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
1976 }
1977 } else if (key->isEqualTo(coregraphics_progress_string.get())) {
1978 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1979 uint32_t data = n->unsigned32BitValue();
1980 pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
1981 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
1982 }
1983 } else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
1984 key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
1985 key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
1986 key->isEqualTo(stall_halt_string.get())) {
1987 if ((b = OSDynamicCast(OSBoolean, obj))) {
1988 setProperty(key, b);
1989 }
1990 } else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
1991 key->isEqualTo(kIOPMDeepSleepTimerKey) ||
1992 key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
1993 key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
1994 if ((n = OSDynamicCast(OSNumber, obj))) {
1995 setProperty(key, n);
1996 }
1997 } else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
1998 if (kOSBooleanTrue == obj) {
1999 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2000 } else {
2001 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2002 }
2003 DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
2004 }
2005 #if DEBUG || DEVELOPMENT
2006 else if (key->isEqualTo(clamshell_close_string.get())) {
2007 DLOG("SetProperties: setting clamshell close\n");
2008 UInt32 msg = kIOPMClamshellClosed;
2009 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2010 } else if (key->isEqualTo(clamshell_open_string.get())) {
2011 DLOG("SetProperties: setting clamshell open\n");
2012 UInt32 msg = kIOPMClamshellOpened;
2013 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2014 } else if (key->isEqualTo(ac_detach_string.get())) {
2015 DLOG("SetProperties: setting ac detach\n");
2016 UInt32 msg = kIOPMSetACAdaptorConnected;
2017 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2018 } else if (key->isEqualTo(ac_attach_string.get())) {
2019 DLOG("SetProperties: setting ac attach\n");
2020 UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue;
2021 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2022 } else if (key->isEqualTo(desktopmode_set_string.get())) {
2023 DLOG("SetProperties: setting desktopmode");
2024 UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue;
2025 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2026 } else if (key->isEqualTo(desktopmode_remove_string.get())) {
2027 DLOG("SetProperties: removing desktopmode\n");
2028 UInt32 msg = kIOPMSetDesktopMode;
2029 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2030 }
2031 #endif
2032 // Relay our allowed PM settings onto our registered PM clients
2033 else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
2034 return_value = setPMSetting(key, obj);
2035 if (kIOReturnSuccess != return_value) {
2036 break;
2037 }
2038 } else {
2039 DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
2040 }
2041 }
2042
2043 exit:
2044 return return_value;
2045 }
2046
2047 // MARK: -
2048 // MARK: Aggressiveness
2049
2050 //******************************************************************************
2051 // setAggressiveness
2052 //
2053 // Override IOService::setAggressiveness()
2054 //******************************************************************************
2055
2056 IOReturn
setAggressiveness(unsigned long type,unsigned long value)2057 IOPMrootDomain::setAggressiveness(
2058 unsigned long type,
2059 unsigned long value )
2060 {
2061 return setAggressiveness( type, value, 0 );
2062 }
2063
2064 /*
2065 * Private setAggressiveness() with an internal options argument.
2066 */
2067 IOReturn
setAggressiveness(unsigned long type,unsigned long value,IOOptionBits options)2068 IOPMrootDomain::setAggressiveness(
2069 unsigned long type,
2070 unsigned long value,
2071 IOOptionBits options )
2072 {
2073 AggressivesRequest * entry;
2074 AggressivesRequest * request;
2075 bool found = false;
2076
2077 if ((type > UINT_MAX) || (value > UINT_MAX)) {
2078 return kIOReturnBadArgument;
2079 }
2080
2081 if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2082 DLOG("setAggressiveness(%x) %s = %u\n",
2083 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2084 } else {
2085 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2086 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2087 }
2088
2089 request = IOMallocType(AggressivesRequest);
2090 request->options = options;
2091 request->dataType = kAggressivesRequestTypeRecord;
2092 request->data.record.type = (uint32_t) type;
2093 request->data.record.value = (uint32_t) value;
2094
2095 AGGRESSIVES_LOCK();
2096
2097 // Update disk quick spindown flag used by getAggressiveness().
2098 // Never merge requests with quick spindown flags set.
2099
2100 if (options & kAggressivesOptionQuickSpindownEnable) {
2101 gAggressivesState |= kAggressivesStateQuickSpindown;
2102 } else if (options & kAggressivesOptionQuickSpindownDisable) {
2103 gAggressivesState &= ~kAggressivesStateQuickSpindown;
2104 } else {
2105 // Coalesce requests with identical aggressives types.
2106 // Deal with callers that calls us too "aggressively".
2107
2108 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2109 {
2110 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2111 (entry->data.record.type == type) &&
2112 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2113 entry->data.record.value = (uint32_t) value;
2114 found = true;
2115 break;
2116 }
2117 }
2118 }
2119
2120 if (!found) {
2121 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2122 }
2123
2124 AGGRESSIVES_UNLOCK();
2125
2126 if (found) {
2127 IOFreeType(request, AggressivesRequest);
2128 }
2129
2130 if (options & kAggressivesOptionSynchronous) {
2131 handleAggressivesRequests(); // not truly synchronous
2132 } else {
2133 thread_call_enter(aggressivesThreadCall);
2134 }
2135
2136 return kIOReturnSuccess;
2137 }
2138
2139 //******************************************************************************
2140 // getAggressiveness
2141 //
2142 // Override IOService::setAggressiveness()
2143 // Fetch the aggressiveness factor with the given type.
2144 //******************************************************************************
2145
2146 IOReturn
getAggressiveness(unsigned long type,unsigned long * outLevel)2147 IOPMrootDomain::getAggressiveness(
2148 unsigned long type,
2149 unsigned long * outLevel )
2150 {
2151 uint32_t value = 0;
2152 int source = 0;
2153
2154 if (!outLevel || (type > UINT_MAX)) {
2155 return kIOReturnBadArgument;
2156 }
2157
2158 AGGRESSIVES_LOCK();
2159
2160 // Disk quick spindown in effect, report value = 1
2161
2162 if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2163 (type == kPMMinutesToSpinDown)) {
2164 value = kAggressivesMinValue;
2165 source = 1;
2166 }
2167
2168 // Consult the pending request queue.
2169
2170 if (!source) {
2171 AggressivesRequest * entry;
2172
2173 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2174 {
2175 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2176 (entry->data.record.type == type) &&
2177 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2178 value = entry->data.record.value;
2179 source = 2;
2180 break;
2181 }
2182 }
2183 }
2184
2185 // Consult the backend records.
2186
2187 if (!source && aggressivesData) {
2188 AggressivesRecord * record;
2189 int i, count;
2190
2191 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2192 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2193
2194 for (i = 0; i < count; i++, record++) {
2195 if (record->type == type) {
2196 value = record->value;
2197 source = 3;
2198 break;
2199 }
2200 }
2201 }
2202
2203 AGGRESSIVES_UNLOCK();
2204
2205 if (source) {
2206 *outLevel = (unsigned long) value;
2207 return kIOReturnSuccess;
2208 } else {
2209 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
2210 *outLevel = 0; // default return = 0, driver may not check for error
2211 return kIOReturnInvalid;
2212 }
2213 }
2214
2215 //******************************************************************************
2216 // joinAggressiveness
2217 //
2218 // Request from IOService to join future aggressiveness broadcasts.
2219 //******************************************************************************
2220
2221 IOReturn
joinAggressiveness(IOService * service)2222 IOPMrootDomain::joinAggressiveness(
2223 IOService * service )
2224 {
2225 AggressivesRequest * request;
2226
2227 if (!service || (service == this)) {
2228 return kIOReturnBadArgument;
2229 }
2230
2231 DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2232
2233 request = IOMallocType(AggressivesRequest);
2234 request->dataType = kAggressivesRequestTypeService;
2235 request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2236
2237 AGGRESSIVES_LOCK();
2238 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2239 AGGRESSIVES_UNLOCK();
2240
2241 thread_call_enter(aggressivesThreadCall);
2242
2243 return kIOReturnSuccess;
2244 }
2245
2246 //******************************************************************************
2247 // handleAggressivesRequests
2248 //
2249 // Backend thread processes all incoming aggressiveness requests in the queue.
2250 //******************************************************************************
2251
2252 static void
handleAggressivesFunction(thread_call_param_t param1,thread_call_param_t param2)2253 handleAggressivesFunction(
2254 thread_call_param_t param1,
2255 thread_call_param_t param2 )
2256 {
2257 if (param1) {
2258 ((IOPMrootDomain *) param1)->handleAggressivesRequests();
2259 }
2260 }
2261
2262 void
handleAggressivesRequests(void)2263 IOPMrootDomain::handleAggressivesRequests( void )
2264 {
2265 AggressivesRecord * start;
2266 AggressivesRecord * record;
2267 AggressivesRequest * request;
2268 queue_head_t joinedQueue;
2269 int i, count;
2270 bool broadcast;
2271 bool found;
2272 bool pingSelf = false;
2273
2274 AGGRESSIVES_LOCK();
2275
2276 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2277 queue_empty(&aggressivesQueue)) {
2278 goto unlock_done;
2279 }
2280
2281 gAggressivesState |= kAggressivesStateBusy;
2282 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2283 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2284
2285 do{
2286 broadcast = false;
2287 queue_init(&joinedQueue);
2288
2289 do{
2290 // Remove request from the incoming queue in FIFO order.
2291 queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
2292 switch (request->dataType) {
2293 case kAggressivesRequestTypeRecord:
2294 // Update existing record if found.
2295 found = false;
2296 for (i = 0, record = start; i < count; i++, record++) {
2297 if (record->type == request->data.record.type) {
2298 found = true;
2299
2300 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2301 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2302 broadcast = true;
2303 record->flags |= (kAggressivesRecordFlagMinValue |
2304 kAggressivesRecordFlagModified);
2305 DLOG("disk spindown accelerated, was %u min\n",
2306 record->value);
2307 }
2308 } else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2309 if (record->flags & kAggressivesRecordFlagMinValue) {
2310 broadcast = true;
2311 record->flags |= kAggressivesRecordFlagModified;
2312 record->flags &= ~kAggressivesRecordFlagMinValue;
2313 DLOG("disk spindown restored to %u min\n",
2314 record->value);
2315 }
2316 } else if (record->value != request->data.record.value) {
2317 record->value = request->data.record.value;
2318 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2319 broadcast = true;
2320 record->flags |= kAggressivesRecordFlagModified;
2321 }
2322 }
2323 break;
2324 }
2325 }
2326
2327 // No matching record, append a new record.
2328 if (!found &&
2329 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2330 AggressivesRecord newRecord;
2331
2332 newRecord.flags = kAggressivesRecordFlagModified;
2333 newRecord.type = request->data.record.type;
2334 newRecord.value = request->data.record.value;
2335 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2336 newRecord.flags |= kAggressivesRecordFlagMinValue;
2337 DLOG("disk spindown accelerated\n");
2338 }
2339
2340 aggressivesData->appendValue(newRecord);
2341
2342 // OSData may have switched to another (larger) buffer.
2343 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2344 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2345 broadcast = true;
2346 }
2347
2348 // Finished processing the request, release it.
2349 IOFreeType(request, AggressivesRequest);
2350 break;
2351
2352 case kAggressivesRequestTypeService:
2353 // synchronizeAggressives() will free request.
2354 queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2355 break;
2356
2357 default:
2358 panic("bad aggressives request type %x", request->dataType);
2359 break;
2360 }
2361 } while (!queue_empty(&aggressivesQueue));
2362
2363 // Release the lock to perform work, with busy flag set.
2364 if (!queue_empty(&joinedQueue) || broadcast) {
2365 AGGRESSIVES_UNLOCK();
2366 if (!queue_empty(&joinedQueue)) {
2367 synchronizeAggressives(&joinedQueue, start, count);
2368 }
2369 if (broadcast) {
2370 broadcastAggressives(start, count);
2371 }
2372 AGGRESSIVES_LOCK();
2373 }
2374
2375 // Remove the modified flag from all records.
2376 for (i = 0, record = start; i < count; i++, record++) {
2377 if ((record->flags & kAggressivesRecordFlagModified) &&
2378 ((record->type == kPMMinutesToDim) ||
2379 (record->type == kPMMinutesToSleep))) {
2380 pingSelf = true;
2381 }
2382
2383 record->flags &= ~kAggressivesRecordFlagModified;
2384 }
2385
2386 // Check the incoming queue again since new entries may have been
2387 // added while lock was released above.
2388 } while (!queue_empty(&aggressivesQueue));
2389
2390 gAggressivesState &= ~kAggressivesStateBusy;
2391
2392 unlock_done:
2393 AGGRESSIVES_UNLOCK();
2394
2395 // Root domain is interested in system and display sleep slider changes.
2396 // Submit a power event to handle those changes on the PM work loop.
2397
2398 if (pingSelf && pmPowerStateQueue) {
2399 pmPowerStateQueue->submitPowerEvent(
2400 kPowerEventPolicyStimulus,
2401 (void *) kStimulusAggressivenessChanged );
2402 }
2403 }
2404
2405 //******************************************************************************
2406 // synchronizeAggressives
2407 //
2408 // Push all known aggressiveness records to one or more IOService.
2409 //******************************************************************************
2410
2411 void
synchronizeAggressives(queue_head_t * joinedQueue,const AggressivesRecord * array,int count)2412 IOPMrootDomain::synchronizeAggressives(
2413 queue_head_t * joinedQueue,
2414 const AggressivesRecord * array,
2415 int count )
2416 {
2417 OSSharedPtr<IOService> service;
2418 AggressivesRequest * request;
2419 const AggressivesRecord * record;
2420 IOPMDriverCallEntry callEntry;
2421 uint32_t value;
2422 int i;
2423
2424 while (!queue_empty(joinedQueue)) {
2425 queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
2426 if (request->dataType == kAggressivesRequestTypeService) {
2427 // retained by joinAggressiveness(), so take ownership
2428 service = os::move(request->data.service);
2429 } else {
2430 service.reset();
2431 }
2432
2433 IOFreeType(request, AggressivesRequest);
2434 request = NULL;
2435
2436 if (service) {
2437 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2438 for (i = 0, record = array; i < count; i++, record++) {
2439 value = record->value;
2440 if (record->flags & kAggressivesRecordFlagMinValue) {
2441 value = kAggressivesMinValue;
2442 }
2443
2444 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2445 record->type, value, service->getName());
2446 service->setAggressiveness(record->type, value);
2447 }
2448 service->deassertPMDriverCall(&callEntry);
2449 }
2450 }
2451 }
2452 }
2453
2454 //******************************************************************************
2455 // broadcastAggressives
2456 //
2457 // Traverse PM tree and call setAggressiveness() for records that have changed.
2458 //******************************************************************************
2459
2460 void
broadcastAggressives(const AggressivesRecord * array,int count)2461 IOPMrootDomain::broadcastAggressives(
2462 const AggressivesRecord * array,
2463 int count )
2464 {
2465 OSSharedPtr<IORegistryIterator> iter;
2466 IORegistryEntry *entry;
2467 OSSharedPtr<IORegistryEntry> child;
2468 IOPowerConnection *connect;
2469 IOService *service;
2470 const AggressivesRecord *record;
2471 IOPMDriverCallEntry callEntry;
2472 uint32_t value;
2473 int i;
2474
2475 iter = IORegistryIterator::iterateOver(
2476 this, gIOPowerPlane, kIORegistryIterateRecursively);
2477 if (iter) {
2478 do{
2479 // !! reset the iterator
2480 iter->reset();
2481 while ((entry = iter->getNextObject())) {
2482 connect = OSDynamicCast(IOPowerConnection, entry);
2483 if (!connect || !connect->getReadyFlag()) {
2484 continue;
2485 }
2486
2487 child = connect->copyChildEntry(gIOPowerPlane);
2488 if (child) {
2489 if ((service = OSDynamicCast(IOService, child.get()))) {
2490 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2491 for (i = 0, record = array; i < count; i++, record++) {
2492 if (record->flags & kAggressivesRecordFlagModified) {
2493 value = record->value;
2494 if (record->flags & kAggressivesRecordFlagMinValue) {
2495 value = kAggressivesMinValue;
2496 }
2497 _LOG("broadcastAggressives %x = %u to %s\n",
2498 record->type, value, service->getName());
2499 service->setAggressiveness(record->type, value);
2500 }
2501 }
2502 service->deassertPMDriverCall(&callEntry);
2503 }
2504 }
2505 }
2506 }
2507 }while (!entry && !iter->isValid());
2508 }
2509 }
2510
2511 //*****************************************
2512 // stackshot on power button press
2513 // ***************************************
2514 static void
powerButtonDownCallout(thread_call_param_t us,thread_call_param_t)2515 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2516 {
2517 /* Power button pressed during wake
2518 * Take a stackshot
2519 */
2520 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2521 ((IOPMrootDomain *)us)->takeStackshot(false);
2522 }
2523
2524 static void
powerButtonUpCallout(thread_call_param_t us,thread_call_param_t)2525 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2526 {
2527 /* Power button released.
2528 * Delete any stackshot data
2529 */
2530 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2531 ((IOPMrootDomain *)us)->deleteStackshot();
2532 }
2533 //*************************************************************************
2534 //
2535
2536 // MARK: -
2537 // MARK: System Sleep
2538
2539 //******************************************************************************
2540 // startIdleSleepTimer
2541 //
2542 //******************************************************************************
2543
2544 void
startIdleSleepTimer(uint32_t inMilliSeconds)2545 IOPMrootDomain::startIdleSleepTimer( uint32_t inMilliSeconds )
2546 {
2547 AbsoluteTime deadline;
2548
2549 ASSERT_GATED();
2550 if (gNoIdleFlag) {
2551 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2552 return;
2553 }
2554 if (inMilliSeconds) {
2555 if (inMilliSeconds < kMinimumTimeBeforeIdleSleep) {
2556 AbsoluteTime now;
2557 uint64_t nsec_since_wake;
2558 uint64_t msec_since_wake;
2559
2560 // Adjust idle timer so it will not expire until atleast kMinimumTimeBeforeIdleSleep milliseconds
2561 // after the most recent AP wake.
2562 clock_get_uptime(&now);
2563 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2564 absolutetime_to_nanoseconds(now, &nsec_since_wake);
2565 msec_since_wake = nsec_since_wake / NSEC_PER_MSEC;
2566
2567 if (msec_since_wake < kMinimumTimeBeforeIdleSleep) {
2568 uint32_t newIdleTimer = kMinimumTimeBeforeIdleSleep - (uint32_t)msec_since_wake;
2569
2570 // Ensure that our new idle timer is not less than inMilliSeconds,
2571 // as we should only be increasing the timer duration, not decreasing it
2572 if (newIdleTimer > inMilliSeconds) {
2573 DLOG("startIdleSleepTimer increasing timeout from %u to %u\n", inMilliSeconds, newIdleTimer);
2574 inMilliSeconds = newIdleTimer;
2575 }
2576 }
2577 }
2578 clock_interval_to_deadline(inMilliSeconds, kMillisecondScale, &deadline);
2579 thread_call_enter_delayed(extraSleepTimer, deadline);
2580 idleSleepTimerPending = true;
2581 } else {
2582 thread_call_enter(extraSleepTimer);
2583 }
2584 DLOG("idle timer set for %u milliseconds\n", inMilliSeconds);
2585 }
2586
2587 //******************************************************************************
2588 // cancelIdleSleepTimer
2589 //
2590 //******************************************************************************
2591
2592 void
cancelIdleSleepTimer(void)2593 IOPMrootDomain::cancelIdleSleepTimer( void )
2594 {
2595 ASSERT_GATED();
2596 if (idleSleepTimerPending) {
2597 DLOG("idle timer cancelled\n");
2598 thread_call_cancel(extraSleepTimer);
2599 idleSleepTimerPending = false;
2600
2601 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2602 AbsoluteTime now;
2603 clock_usec_t microsecs;
2604 clock_get_uptime(&now);
2605 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2606 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
2607 if (assertOnWakeReport) {
2608 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2609 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2610 }
2611 }
2612 }
2613 }
2614
2615 //******************************************************************************
2616 // idleSleepTimerExpired
2617 //
2618 //******************************************************************************
2619
2620 static void
idleSleepTimerExpired(thread_call_param_t us,thread_call_param_t)2621 idleSleepTimerExpired(
2622 thread_call_param_t us, thread_call_param_t )
2623 {
2624 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2625 }
2626
2627 //******************************************************************************
2628 // handleSleepTimerExpiration
2629 //
2630 // The time between the sleep idle timeout and the next longest one has elapsed.
2631 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2632 //******************************************************************************
2633
2634 void
handleSleepTimerExpiration(void)2635 IOPMrootDomain::handleSleepTimerExpiration( void )
2636 {
2637 if (!gIOPMWorkLoop->inGate()) {
2638 gIOPMWorkLoop->runAction(
2639 OSMemberFunctionCast(IOWorkLoop::Action, this,
2640 &IOPMrootDomain::handleSleepTimerExpiration),
2641 this);
2642 return;
2643 }
2644
2645 DLOG("sleep timer expired\n");
2646 ASSERT_GATED();
2647
2648 idleSleepTimerPending = false;
2649 setQuickSpinDownTimeout();
2650 adjustPowerState(true);
2651 }
2652
2653 //******************************************************************************
2654 // getTimeToIdleSleep
2655 //
2656 // Returns number of milliseconds left before going into idle sleep.
2657 // Caller has to make sure that idle sleep is allowed at the time of calling
2658 // this function
2659 //******************************************************************************
2660
2661 uint32_t
getTimeToIdleSleep(void)2662 IOPMrootDomain::getTimeToIdleSleep( void )
2663 {
2664 AbsoluteTime now, lastActivityTime;
2665 uint64_t nanos;
2666 uint32_t minutesSinceUserInactive = 0;
2667 uint32_t sleepDelay = 0;
2668
2669 if (!idleSleepEnabled) {
2670 return 0xffffffff;
2671 }
2672
2673 if (userActivityTime) {
2674 lastActivityTime = userActivityTime;
2675 } else {
2676 lastActivityTime = userBecameInactiveTime;
2677 }
2678
2679 // Ignore any lastActivityTime that predates the last system wake.
2680 // The goal is to avoid a sudden idle sleep right after a dark wake
2681 // due to sleepDelay=0 computed below. The alternative 60s minimum
2682 // timeout should be large enough to allow dark wake to complete,
2683 // at which point the idle timer will be promptly cancelled.
2684 clock_get_uptime(&now);
2685 if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) &&
2686 (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) {
2687 SUB_ABSOLUTETIME(&now, &lastActivityTime);
2688 absolutetime_to_nanoseconds(now, &nanos);
2689 minutesSinceUserInactive = nanos / (60000000000ULL);
2690
2691 if (minutesSinceUserInactive >= sleepSlider) {
2692 sleepDelay = 0;
2693 } else {
2694 sleepDelay = sleepSlider - minutesSinceUserInactive;
2695 }
2696 } else {
2697 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2698 lastActivityTime, now, gIOLastWakeAbsTime);
2699 sleepDelay = sleepSlider;
2700 }
2701
2702 DLOG("user inactive %u min, time to idle sleep %u min\n",
2703 minutesSinceUserInactive, sleepDelay);
2704
2705 return sleepDelay * 60 * 1000;
2706 }
2707
2708 //******************************************************************************
2709 // setQuickSpinDownTimeout
2710 //
2711 //******************************************************************************
2712
2713 void
setQuickSpinDownTimeout(void)2714 IOPMrootDomain::setQuickSpinDownTimeout( void )
2715 {
2716 ASSERT_GATED();
2717 setAggressiveness(
2718 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2719 }
2720
2721 //******************************************************************************
2722 // restoreUserSpinDownTimeout
2723 //
2724 //******************************************************************************
2725
2726 void
restoreUserSpinDownTimeout(void)2727 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2728 {
2729 ASSERT_GATED();
2730 setAggressiveness(
2731 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2732 }
2733
2734 //******************************************************************************
2735 // sleepSystem
2736 //
2737 //******************************************************************************
2738
2739 /* public */
2740 IOReturn
sleepSystem(void)2741 IOPMrootDomain::sleepSystem( void )
2742 {
2743 return sleepSystemOptions(NULL);
2744 }
2745
2746 /* private */
2747 IOReturn
sleepSystemOptions(OSDictionary * options)2748 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2749 {
2750 OSObject *obj = NULL;
2751 OSString *reason = NULL;
2752 /* sleepSystem is a public function, and may be called by any kernel driver.
2753 * And that's bad - drivers should sleep the system by calling
2754 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2755 *
2756 * Note that user space app calls to IOPMSleepSystem() will also travel
2757 * this code path and thus be correctly identified as software sleeps.
2758 */
2759
2760 if (options && options->getObject("OSSwitch")) {
2761 // Log specific sleep cause for OS Switch hibernation
2762 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2763 }
2764
2765 if (options && (obj = options->getObject("Sleep Reason"))) {
2766 reason = OSDynamicCast(OSString, obj);
2767 if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2768 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2769 }
2770 if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2771 return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2772 }
2773 }
2774
2775 return privateSleepSystem( kIOPMSleepReasonSoftware);
2776 }
2777
2778 /* private */
2779 IOReturn
privateSleepSystem(uint32_t sleepReason)2780 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2781 {
2782 /* Called from both gated and non-gated context */
2783
2784 if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2785 return kIOReturnNotPermitted;
2786 }
2787
2788 pmPowerStateQueue->submitPowerEvent(
2789 kPowerEventPolicyStimulus,
2790 (void *) kStimulusDemandSystemSleep,
2791 sleepReason);
2792
2793 return kIOReturnSuccess;
2794 }
2795
2796 //******************************************************************************
2797 // powerChangeDone
2798 //
2799 // This overrides powerChangeDone in IOService.
2800 //******************************************************************************
2801 void
powerChangeDone(unsigned long previousPowerState)2802 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2803 {
2804 #if !__i386__ && !__x86_64__
2805 uint64_t timeSinceReset = 0;
2806 #endif
2807 uint64_t now;
2808 unsigned long newState;
2809 clock_sec_t secs;
2810 clock_usec_t microsecs;
2811 uint32_t lastDebugWakeSeconds;
2812 clock_sec_t adjWakeTime;
2813 IOPMCalendarStruct nowCalendar;
2814
2815 ASSERT_GATED();
2816 newState = getPowerState();
2817 DLOG("PowerChangeDone: %s->%s\n",
2818 getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2819
2820 if (previousPowerState == newState) {
2821 return;
2822 }
2823
2824 notifierThread = current_thread();
2825 switch (getPowerState()) {
2826 case SLEEP_STATE: {
2827 if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2828 secs = 0;
2829 microsecs = 0;
2830 PEGetUTCTimeOfDay(&secs, µsecs);
2831
2832 adjWakeTime = 0;
2833 if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) {
2834 IOLog("use _calendarWakeAlarmUTC\n");
2835 adjWakeTime = _calendarWakeAlarmUTC;
2836 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
2837 IOLog("accelerate _aotWakeTime for exit\n");
2838 adjWakeTime = secs;
2839 } else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2840 IOLog("accelerate _aotWakeTime for assertion\n");
2841 adjWakeTime = secs;
2842 }
2843 if (adjWakeTime) {
2844 IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2845 }
2846
2847 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2848 IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2849
2850 IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2851 assert(kIOReturnSuccess == ret);
2852 }
2853 if (_aotLastWakeTime) {
2854 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
2855 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
2856 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
2857 gWakeReasonString,
2858 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2859 }
2860 }
2861 _aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2862 if (_aotTimerScheduled) {
2863 _aotTimerES->cancelTimeout();
2864 _aotTimerScheduled = false;
2865 }
2866 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2867
2868 // re-enable this timer for next sleep
2869 cancelIdleSleepTimer();
2870
2871 if (clamshellExists) {
2872 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
2873 if (gClamshellFlags & kClamshell_WAR_58009435) {
2874 // Disable clamshell sleep until system has completed full wake.
2875 // This prevents a system sleep request (due to a clamshell close)
2876 // from being queued until the end of system full wake - even if
2877 // other clamshell disable bits outside of our control is wrong.
2878 setClamShellSleepDisable(true, kClamshellSleepDisableInternal);
2879 }
2880 #endif
2881
2882 // Log the last known clamshell state before system sleep
2883 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
2884 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask,
2885 desktopMode, acAdaptorConnected);
2886 }
2887
2888 clock_get_calendar_absolute_and_microtime(&secs, µsecs, &now);
2889 logtime(secs);
2890 gIOLastSleepTime.tv_sec = secs;
2891 gIOLastSleepTime.tv_usec = microsecs;
2892 if (!_aotLastWakeTime) {
2893 gIOLastUserSleepTime = gIOLastSleepTime;
2894 }
2895
2896 gIOLastWakeTime.tv_sec = 0;
2897 gIOLastWakeTime.tv_usec = 0;
2898 gIOLastSleepAbsTime = now;
2899
2900 if (wake2DarkwakeDelay && sleepDelaysReport) {
2901 clock_sec_t wake2DarkwakeSecs, darkwake2SleepSecs;
2902 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2903
2904 SUB_ABSOLUTETIME(&now, &ts_sleepStart);
2905 absolutetime_to_microtime(now, &darkwake2SleepSecs, µsecs);
2906 absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, µsecs);
2907 HISTREPORT_TALLYVALUE(sleepDelaysReport,
2908 (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
2909
2910 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
2911 wake2DarkwakeDelay = 0;
2912 }
2913 #if HIBERNATION
2914 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2915 #if (DEVELOPMENT || DEBUG)
2916 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2917 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2918 "System State",
2919 gIOHibernateState ? "Enter Hibernate" : "Enter Sleep"
2920 );
2921 #endif /* DEVELOPMENT || DEBUG */
2922 IOHibernateSystemHasSlept();
2923
2924 evaluateSystemSleepPolicyFinal();
2925 #else
2926 LOG("System Sleep\n");
2927 #if (DEVELOPMENT || DEBUG)
2928 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2929 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2930 "System State", "Enter Sleep");
2931 #endif /* DEVELOPMENT || DEBUG */
2932 #endif
2933 if (thermalWarningState) {
2934 OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
2935 if (event) {
2936 systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
2937 }
2938 }
2939 assertOnWakeSecs = 0;
2940 lowBatteryCondition = false;
2941 thermalEmergencyState = false;
2942
2943 #if DEVELOPMENT || DEBUG
2944 extern int g_should_log_clock_adjustments;
2945 if (g_should_log_clock_adjustments) {
2946 clock_sec_t secs = 0;
2947 clock_usec_t microsecs = 0;
2948 uint64_t now_b = mach_absolute_time();
2949
2950 secs = 0;
2951 microsecs = 0;
2952 PEGetUTCTimeOfDay(&secs, µsecs);
2953
2954 uint64_t now_a = mach_absolute_time();
2955 os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2956 __func__, (unsigned long)secs, microsecs, now_b, now_a);
2957 }
2958 #endif
2959
2960 getPlatform()->sleepKernel();
2961
2962 // The CPU(s) are off at this point,
2963 // Code will resume execution here upon wake.
2964
2965 clock_get_uptime(&gIOLastWakeAbsTime);
2966 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
2967 #if DEVELOPMENT || DEBUG
2968 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2969 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2970 "System State", "Waking Up"
2971 );
2972 #endif /* DEVELOPMENT || DEBUG */
2973 _highestCapability = 0;
2974
2975 #if HIBERNATION
2976 IOHibernateSystemWake();
2977 #endif
2978
2979 // sleep transition complete
2980 gSleepOrShutdownPending = 0;
2981
2982 // trip the reset of the calendar clock
2983 clock_wakeup_calendar();
2984 clock_get_calendar_microtime(&secs, µsecs);
2985 gIOLastWakeTime.tv_sec = secs;
2986 gIOLastWakeTime.tv_usec = microsecs;
2987
2988 // aot
2989 if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
2990 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
2991 secs = 0;
2992 microsecs = 0;
2993 PEGetUTCTimeOfDay(&secs, µsecs);
2994 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2995 IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2996 _aotMetrics->sleepCount++;
2997 _aotLastWakeTime = gIOLastWakeAbsTime;
2998 if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
2999 _aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
3000 = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
3001 _aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
3002 = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
3003 }
3004
3005 if (_aotTestTime) {
3006 if (_aotWakeTimeUTC <= secs) {
3007 _aotTestTime = _aotTestTime + _aotTestInterval;
3008 }
3009 setWakeTime(_aotTestTime);
3010 }
3011 }
3012
3013 #if HIBERNATION
3014 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
3015 #endif
3016
3017 lastSleepReason = 0;
3018
3019 lastDebugWakeSeconds = _debugWakeSeconds;
3020 _debugWakeSeconds = 0;
3021 _scheduledAlarmMask = 0;
3022 _nextScheduledAlarmType = NULL;
3023
3024 darkWakeExit = false;
3025 darkWakePowerClamped = false;
3026 darkWakePostTickle = false;
3027 darkWakeHibernateError = false;
3028 darkWakeToSleepASAP = true;
3029 darkWakeLogClamp = true;
3030 sleepTimerMaintenance = false;
3031 sleepToStandby = false;
3032 wranglerTickled = false;
3033 userWasActive = false;
3034 isRTCAlarmWake = false;
3035 clamshellIgnoreClose = false;
3036 fullWakeReason = kFullWakeReasonNone;
3037 idleSleepRevertible = true;
3038
3039 #if defined(__i386__) || defined(__x86_64__)
3040 kdebugTrace(kPMLogSystemWake, 0, 0, 0);
3041
3042 OSSharedPtr<OSObject> wakeTypeProp = copyProperty(kIOPMRootDomainWakeTypeKey);
3043 OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey);
3044 OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get());
3045 OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get());
3046
3047 if (wakeReason && (wakeReason->getLength() >= 2) &&
3048 gWakeReasonString[0] == '\0') {
3049 WAKEEVENT_LOCK();
3050 // Until the platform driver can claim its wake reasons
3051 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
3052 sizeof(gWakeReasonString));
3053 if (!gWakeReasonSysctlRegistered) {
3054 gWakeReasonSysctlRegistered = true;
3055 }
3056 WAKEEVENT_UNLOCK();
3057 }
3058
3059 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
3060 lowBatteryCondition = true;
3061 darkWakeMaintenance = true;
3062 } else {
3063 #if HIBERNATION
3064 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3065 OSNumber * hibOptions = OSDynamicCast( OSNumber, hibOptionsProp.get());
3066 if (hibernateAborted || ((hibOptions &&
3067 !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
3068 // Hibernate aborted, or EFI brought up graphics
3069 darkWakeExit = true;
3070 if (hibernateAborted) {
3071 DLOG("Hibernation aborted\n");
3072 } else {
3073 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
3074 }
3075 } else
3076 #endif
3077 if (wakeType && (
3078 wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
3079 wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
3080 // User wake or RTC alarm
3081 darkWakeExit = true;
3082 if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
3083 isRTCAlarmWake = true;
3084 }
3085 } else if (wakeType &&
3086 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
3087 // SMC standby timer trumps SleepX
3088 darkWakeMaintenance = true;
3089 sleepTimerMaintenance = true;
3090 } else if ((lastDebugWakeSeconds != 0) &&
3091 ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
3092 // SleepX before maintenance
3093 darkWakeExit = true;
3094 } else if (wakeType &&
3095 wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
3096 darkWakeMaintenance = true;
3097 } else if (wakeType &&
3098 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
3099 darkWakeMaintenance = true;
3100 darkWakeSleepService = true;
3101 #if HIBERNATION
3102 if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3103 sleepToStandby = true;
3104 }
3105 #endif
3106 } else if (wakeType &&
3107 wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3108 darkWakeMaintenance = true;
3109 darkWakeHibernateError = true;
3110 } else {
3111 // Unidentified wake source, resume to full wake if debug
3112 // alarm is pending.
3113
3114 if (lastDebugWakeSeconds &&
3115 (!wakeReason || wakeReason->isEqualTo(""))) {
3116 darkWakeExit = true;
3117 }
3118 }
3119 }
3120
3121 if (darkWakeExit) {
3122 darkWakeToSleepASAP = false;
3123 fullWakeReason = kFullWakeReasonLocalUser;
3124 reportUserInput();
3125 } else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
3126 handleSetDisplayPowerOn(true);
3127 } else if (!darkWakeMaintenance) {
3128 // Early/late tickle for non-maintenance wake.
3129 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) {
3130 darkWakePostTickle = true;
3131 }
3132 }
3133 #else /* !__i386__ && !__x86_64__ */
3134 timeSinceReset = ml_get_time_since_reset();
3135 kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3136
3137 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) {
3138 wranglerTickled = true;
3139 fullWakeReason = kFullWakeReasonLocalUser;
3140 requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3141 } else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
3142 isRTCAlarmWake = true;
3143 fullWakeReason = kFullWakeReasonLocalUser;
3144 requestUserActive(this, "RTC debug alarm");
3145 } else {
3146 #if HIBERNATION
3147 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3148 OSNumber * hibOptions = OSDynamicCast(OSNumber, hibOptionsProp.get());
3149 if (hibOptions && !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)) {
3150 fullWakeReason = kFullWakeReasonLocalUser;
3151 requestUserActive(this, "hibernate user wake");
3152 }
3153 #endif
3154 }
3155
3156 // stay awake for at least 30 seconds
3157 startIdleSleepTimer(30 * 1000);
3158 #endif
3159 sleepCnt++;
3160
3161 thread_call_enter(updateConsoleUsersEntry);
3162
3163 // Skip AOT_STATE if we are waking up from an RTC timer.
3164 // This check needs to be done after the epoch change is processed
3165 // and before the changePowerStateWithTagToPriv() call below.
3166 WAKEEVENT_LOCK();
3167 aotShouldExit(false);
3168 WAKEEVENT_UNLOCK();
3169
3170 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
3171 break;
3172 }
3173 #if !__i386__ && !__x86_64__
3174 case ON_STATE:
3175 case AOT_STATE:
3176 {
3177 DLOG("Force re-evaluating aggressiveness\n");
3178 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3179 pmPowerStateQueue->submitPowerEvent(
3180 kPowerEventPolicyStimulus,
3181 (void *) kStimulusNoIdleSleepPreventers );
3182
3183 // After changing to ON_STATE, invalidate any previously queued
3184 // request to change to a state less than ON_STATE. This isn't
3185 // necessary for AOT_STATE or if the device has only one running
3186 // state since the changePowerStateToPriv() issued at the tail
3187 // end of SLEEP_STATE case should take care of that.
3188 if (getPowerState() == ON_STATE) {
3189 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake);
3190 }
3191 break;
3192 }
3193 #endif /* !__i386__ && !__x86_64__ */
3194 }
3195 notifierThread = NULL;
3196 }
3197
3198 //******************************************************************************
3199 // requestPowerDomainState
3200 //
3201 // Extend implementation in IOService. Running on PM work loop thread.
3202 //******************************************************************************
3203
3204 IOReturn
requestPowerDomainState(IOPMPowerFlags childDesire,IOPowerConnection * childConnection,unsigned long specification)3205 IOPMrootDomain::requestPowerDomainState(
3206 IOPMPowerFlags childDesire,
3207 IOPowerConnection * childConnection,
3208 unsigned long specification )
3209 {
3210 // Idle and system sleep prevention flags affects driver desire.
3211 // Children desire are irrelevant so they are cleared.
3212
3213 return super::requestPowerDomainState(0, childConnection, specification);
3214 }
3215
3216
3217 static void
makeSleepPreventersListLog(const OSSharedPtr<OSSet> & preventers,char * buf,size_t buf_size)3218 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3219 {
3220 if (!preventers->getCount()) {
3221 return;
3222 }
3223
3224 char *buf_iter = buf + strlen(buf);
3225 char *buf_end = buf + buf_size;
3226
3227 OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3228 OSObject *obj = NULL;
3229
3230 while ((obj = iterator->getNextObject())) {
3231 IOService *srv = OSDynamicCast(IOService, obj);
3232 if (buf_iter < buf_end) {
3233 buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName());
3234 } else {
3235 DLOG("Print buffer exhausted for sleep preventers list\n");
3236 break;
3237 }
3238 }
3239 }
3240
3241 //******************************************************************************
3242 // updatePreventIdleSleepList
3243 //
3244 // Called by IOService on PM work loop.
3245 // Returns true if PM policy recognized the driver's desire to prevent idle
3246 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3247 //******************************************************************************
3248
3249 bool
updatePreventIdleSleepList(IOService * service,bool addNotRemove)3250 IOPMrootDomain::updatePreventIdleSleepList(
3251 IOService * service, bool addNotRemove)
3252 {
3253 unsigned int oldCount;
3254
3255 oldCount = idleSleepPreventersCount();
3256 return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3257 }
3258
3259 bool
updatePreventIdleSleepListInternal(IOService * service,bool addNotRemove,unsigned int oldCount)3260 IOPMrootDomain::updatePreventIdleSleepListInternal(
3261 IOService * service, bool addNotRemove, unsigned int oldCount)
3262 {
3263 unsigned int newCount;
3264
3265 ASSERT_GATED();
3266
3267 #if defined(XNU_TARGET_OS_OSX)
3268 // Only the display wrangler and no-idle-sleep kernel assertions
3269 // can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3270 // reported by drivers in their power state table is ignored.
3271 if (service && (service != wrangler) && (service != this)) {
3272 return false;
3273 }
3274 #endif
3275
3276 if (service) {
3277 if (addNotRemove) {
3278 preventIdleSleepList->setObject(service);
3279 DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3280 service->getName(), preventIdleSleepList->getCount());
3281 } else if (preventIdleSleepList->member(service)) {
3282 preventIdleSleepList->removeObject(service);
3283 DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3284 service->getName(), preventIdleSleepList->getCount());
3285 }
3286
3287 if (preventIdleSleepList->getCount()) {
3288 char buf[256] = "Idle Sleep Preventers:";
3289 makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3290 DLOG("%s\n", buf);
3291 }
3292 }
3293
3294 newCount = idleSleepPreventersCount();
3295
3296 if ((oldCount == 0) && (newCount != 0)) {
3297 // Driver added to empty prevent list.
3298 // Update the driver desire to prevent idle sleep.
3299 // Driver desire does not prevent demand sleep.
3300
3301 changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent);
3302 } else if ((oldCount != 0) && (newCount == 0)) {
3303 // Last driver removed from prevent list.
3304 // Drop the driver clamp to allow idle sleep.
3305
3306 changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3307 evaluatePolicy( kStimulusNoIdleSleepPreventers );
3308 }
3309 messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3310 &newCount, sizeof(newCount));
3311
3312 #if defined(XNU_TARGET_OS_OSX)
3313 if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
3314 DLOG("Cannot cancel idle sleep\n");
3315 return false; // do not idle-cancel
3316 }
3317 #endif
3318
3319 return true;
3320 }
3321
3322 //******************************************************************************
3323 // startSpinDump
3324 //******************************************************************************
3325
3326 void
startSpinDump(uint32_t spindumpKind)3327 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3328 {
3329 messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3330 }
3331
3332 //******************************************************************************
3333 // preventSystemSleepListUpdate
3334 //
3335 // Called by IOService on PM work loop.
3336 //******************************************************************************
3337
3338 void
updatePreventSystemSleepList(IOService * service,bool addNotRemove)3339 IOPMrootDomain::updatePreventSystemSleepList(
3340 IOService * service, bool addNotRemove )
3341 {
3342 unsigned int oldCount, newCount;
3343
3344 ASSERT_GATED();
3345 if (this == service) {
3346 return;
3347 }
3348
3349 oldCount = preventSystemSleepList->getCount();
3350 if (addNotRemove) {
3351 preventSystemSleepList->setObject(service);
3352 DLOG("Added %s to system sleep preventers list (Total %u)\n",
3353 service->getName(), preventSystemSleepList->getCount());
3354 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
3355 AbsoluteTime now;
3356 clock_usec_t microsecs;
3357 clock_get_uptime(&now);
3358 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3359 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
3360 if (assertOnWakeReport) {
3361 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3362 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3363 }
3364 }
3365 } else if (preventSystemSleepList->member(service)) {
3366 preventSystemSleepList->removeObject(service);
3367 DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3368 service->getName(), preventSystemSleepList->getCount());
3369
3370 if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
3371 // Lost all system sleep preventers.
3372 // Send stimulus if system sleep was blocked, and is in dark wake.
3373 evaluatePolicy( kStimulusDarkWakeEvaluate );
3374 }
3375 }
3376
3377 newCount = preventSystemSleepList->getCount();
3378 if (newCount) {
3379 char buf[256] = "System Sleep Preventers:";
3380 makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3381 DLOG("%s\n", buf);
3382 }
3383
3384 messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3385 &newCount, sizeof(newCount));
3386 }
3387
3388 void
copySleepPreventersList(OSArray ** idleSleepList,OSArray ** systemSleepList)3389 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3390 {
3391 OSSharedPtr<OSCollectionIterator> iterator;
3392 OSObject *object = NULL;
3393 OSSharedPtr<OSArray> array;
3394
3395 if (!gIOPMWorkLoop->inGate()) {
3396 gIOPMWorkLoop->runAction(
3397 OSMemberFunctionCast(IOWorkLoop::Action, this,
3398 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3399 this, (void *)idleSleepList, (void *)systemSleepList);
3400 return;
3401 }
3402
3403 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3404 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3405 array = OSArray::withCapacity(5);
3406
3407 if (iterator && array) {
3408 while ((object = iterator->getNextObject())) {
3409 IOService *service = OSDynamicCast(IOService, object);
3410 if (service) {
3411 OSSharedPtr<const OSSymbol> name = service->copyName();
3412 if (name) {
3413 array->setObject(name.get());
3414 }
3415 }
3416 }
3417 }
3418 *idleSleepList = array.detach();
3419 }
3420
3421 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3422 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3423 array = OSArray::withCapacity(5);
3424
3425 if (iterator && array) {
3426 while ((object = iterator->getNextObject())) {
3427 IOService *service = OSDynamicCast(IOService, object);
3428 if (service) {
3429 OSSharedPtr<const OSSymbol> name = service->copyName();
3430 if (name) {
3431 array->setObject(name.get());
3432 }
3433 }
3434 }
3435 }
3436 *systemSleepList = array.detach();
3437 }
3438 }
3439
3440 void
copySleepPreventersListWithID(OSArray ** idleSleepList,OSArray ** systemSleepList)3441 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3442 {
3443 OSSharedPtr<OSCollectionIterator> iterator;
3444 OSObject *object = NULL;
3445 OSSharedPtr<OSArray> array;
3446
3447 if (!gIOPMWorkLoop->inGate()) {
3448 gIOPMWorkLoop->runAction(
3449 OSMemberFunctionCast(IOWorkLoop::Action, this,
3450 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3451 this, (void *)idleSleepList, (void *)systemSleepList);
3452 return;
3453 }
3454
3455 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3456 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3457 array = OSArray::withCapacity(5);
3458
3459 if (iterator && array) {
3460 while ((object = iterator->getNextObject())) {
3461 IOService *service = OSDynamicCast(IOService, object);
3462 if (service) {
3463 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3464 OSSharedPtr<const OSSymbol> name = service->copyName();
3465 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3466 if (dict && name && id) {
3467 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3468 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3469 array->setObject(dict.get());
3470 }
3471 }
3472 }
3473 }
3474 *idleSleepList = array.detach();
3475 }
3476
3477 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3478 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3479 array = OSArray::withCapacity(5);
3480
3481 if (iterator && array) {
3482 while ((object = iterator->getNextObject())) {
3483 IOService *service = OSDynamicCast(IOService, object);
3484 if (service) {
3485 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3486 OSSharedPtr<const OSSymbol> name = service->copyName();
3487 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3488 if (dict && name && id) {
3489 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3490 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3491 array->setObject(dict.get());
3492 }
3493 }
3494 }
3495 }
3496 *systemSleepList = array.detach();
3497 }
3498 }
3499
3500 //******************************************************************************
3501 // tellChangeDown
3502 //
3503 // Override the superclass implementation to send a different message type.
3504 //******************************************************************************
3505
3506 bool
tellChangeDown(unsigned long stateNum)3507 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3508 {
3509 DLOG("tellChangeDown %s->%s\n",
3510 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3511
3512 if (SLEEP_STATE == stateNum) {
3513 // Legacy apps were already told in the full->dark transition
3514 if (!ignoreTellChangeDown) {
3515 tracePoint( kIOPMTracePointSleepApplications );
3516 } else {
3517 tracePoint( kIOPMTracePointSleepPriorityClients );
3518 }
3519 }
3520
3521 if (!ignoreTellChangeDown) {
3522 userActivityAtSleep = userActivityCount;
3523 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3524
3525 if (SLEEP_STATE == stateNum) {
3526 hibernateAborted = false;
3527
3528 // Direct callout into OSKext so it can disable kext unloads
3529 // during sleep/wake to prevent deadlocks.
3530 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3531
3532 IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3533
3534 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3535 // But tellClientsWithResponse() must be called for both.
3536 ignoreTellChangeDown = true;
3537 }
3538 }
3539
3540 return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3541 }
3542
3543 //******************************************************************************
3544 // askChangeDown
3545 //
3546 // Override the superclass implementation to send a different message type.
3547 // This must be idle sleep since we don't ask during any other power change.
3548 //******************************************************************************
3549
3550 bool
askChangeDown(unsigned long stateNum)3551 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3552 {
3553 DLOG("askChangeDown %s->%s\n",
3554 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3555
3556 // Don't log for dark wake entry
3557 if (kSystemTransitionSleep == _systemTransitionType) {
3558 tracePoint( kIOPMTracePointSleepApplications );
3559 }
3560
3561 return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3562 }
3563
3564 //******************************************************************************
3565 // askChangeDownDone
3566 //
3567 // An opportunity for root domain to cancel the power transition,
3568 // possibily due to an assertion created by powerd in response to
3569 // kIOMessageCanSystemSleep.
3570 //
3571 // Idle sleep:
3572 // full -> dark wake transition
3573 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3574 // 2. askChangeDownDone()
3575 // dark -> sleep transition
3576 // 1. Notify powerd with kIOMessageCanSystemSleep
3577 // 2. askChangeDownDone()
3578 //
3579 // Demand sleep:
3580 // full -> dark wake transition
3581 // 1. Notify powerd with kIOMessageCanSystemSleep
3582 // 2. askChangeDownDone()
3583 // dark -> sleep transition
3584 // 1. Notify powerd with kIOMessageCanSystemSleep
3585 // 2. askChangeDownDone()
3586 //******************************************************************************
3587
3588 void
askChangeDownDone(IOPMPowerChangeFlags * inOutChangeFlags,bool * cancel)3589 IOPMrootDomain::askChangeDownDone(
3590 IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3591 {
3592 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3593 *inOutChangeFlags, *cancel,
3594 _systemTransitionType,
3595 _currentCapability, _pendingCapability);
3596
3597 if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
3598 // Dark->Sleep transition.
3599 // Check if there are any deny sleep assertions.
3600 // lastSleepReason already set by handleOurPowerChangeStart()
3601
3602 if (!checkSystemCanSleep(lastSleepReason)) {
3603 // Cancel dark wake to sleep transition.
3604 // Must re-scan assertions upon entering dark wake.
3605
3606 *cancel = true;
3607 DLOG("cancel dark->sleep\n");
3608 }
3609 if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3610 uint64_t now = mach_continuous_time();
3611 if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3612 && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3613 *cancel = true;
3614 IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3615 }
3616 }
3617 }
3618 }
3619
3620 //******************************************************************************
3621 // systemDidNotSleep
3622 //
3623 // Work common to both canceled or aborted sleep.
3624 //******************************************************************************
3625
3626 void
systemDidNotSleep(void)3627 IOPMrootDomain::systemDidNotSleep( void )
3628 {
3629 // reset console lock state
3630 thread_call_enter(updateConsoleUsersEntry);
3631
3632 if (idleSleepEnabled) {
3633 if (!wrangler) {
3634 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3635 startIdleSleepTimer(kIdleSleepRetryInterval);
3636 #else
3637 startIdleSleepTimer(idleMilliSeconds);
3638 #endif
3639 } else if (!userIsActive) {
3640 // Manually start the idle sleep timer besides waiting for
3641 // the user to become inactive.
3642 startIdleSleepTimer(kIdleSleepRetryInterval);
3643 }
3644 }
3645
3646 preventTransitionToUserActive(false);
3647 IOService::setAdvisoryTickleEnable( true );
3648 idleSleepRevertible = true;
3649
3650 // After idle revert and cancel, send a did-change message to powerd
3651 // to balance the previous will-change message. Kernel clients do not
3652 // need this since sleep cannot be canceled once they are notified.
3653
3654 if (toldPowerdCapWillChange && systemCapabilityNotifier &&
3655 (_pendingCapability != _currentCapability) &&
3656 ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
3657 // Differs from a real capability gain change where notifyRef != 0,
3658 // but it is zero here since no response is expected.
3659
3660 IOPMSystemCapabilityChangeParameters params;
3661
3662 bzero(¶ms, sizeof(params));
3663 params.fromCapabilities = _pendingCapability;
3664 params.toCapabilities = _currentCapability;
3665 params.changeFlags = kIOPMSystemCapabilityDidChange;
3666
3667 DLOG("MESG cap %x->%x did change\n",
3668 params.fromCapabilities, params.toCapabilities);
3669 messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3670 ¶ms, sizeof(params));
3671 }
3672 }
3673
3674 //******************************************************************************
3675 // tellNoChangeDown
3676 //
3677 // Notify registered applications and kernel clients that we are not dropping
3678 // power.
3679 //
3680 // We override the superclass implementation so we can send a different message
3681 // type to the client or application being notified.
3682 //
3683 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3684 //******************************************************************************
3685
3686 void
tellNoChangeDown(unsigned long stateNum)3687 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3688 {
3689 DLOG("tellNoChangeDown %s->%s\n",
3690 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3691
3692 // Sleep canceled, clear the sleep trace point.
3693 tracePoint(kIOPMTracePointSystemUp);
3694
3695 systemDidNotSleep();
3696 return tellClients( kIOMessageSystemWillNotSleep );
3697 }
3698
3699 //******************************************************************************
3700 // tellChangeUp
3701 //
3702 // Notify registered applications and kernel clients that we are raising power.
3703 //
3704 // We override the superclass implementation so we can send a different message
3705 // type to the client or application being notified.
3706 //******************************************************************************
3707
3708 void
tellChangeUp(unsigned long stateNum)3709 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3710 {
3711 DLOG("tellChangeUp %s->%s\n",
3712 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3713
3714 ignoreTellChangeDown = false;
3715
3716 if (stateNum == ON_STATE) {
3717 // Direct callout into OSKext so it can disable kext unloads
3718 // during sleep/wake to prevent deadlocks.
3719 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3720
3721 // Notify platform that sleep was cancelled or resumed.
3722 getPlatform()->callPlatformFunction(
3723 sleepMessagePEFunction.get(), false,
3724 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3725 NULL, NULL, NULL);
3726
3727 if (getPowerState() == ON_STATE) {
3728 // Sleep was cancelled by idle cancel or revert
3729 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
3730 // rdar://problem/50363791
3731 // If system is in dark wake and sleep is cancelled, do not
3732 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3733 // priority clients. They haven't yet seen a SystemWillSleep
3734 // message before the cancellation. So make sure the kernel
3735 // client bit is cleared in _systemMessageClientMask before
3736 // invoking the tellClients() below. This bit may have been
3737 // set by handleOurPowerChangeStart() anticipating a successful
3738 // sleep and setting the filter mask ahead of time allows the
3739 // SystemWillSleep message to go through.
3740 _systemMessageClientMask &= ~kSystemMessageClientKernel;
3741 }
3742
3743 systemDidNotSleep();
3744 tellClients( kIOMessageSystemWillPowerOn );
3745 }
3746
3747 tracePoint( kIOPMTracePointWakeApplications );
3748 tellClients( kIOMessageSystemHasPoweredOn );
3749 } else if (stateNum == AOT_STATE) {
3750 if (getPowerState() == AOT_STATE) {
3751 // Sleep was cancelled by idle cancel or revert
3752 startIdleSleepTimer(idleMilliSeconds);
3753 }
3754 }
3755 }
3756
3757 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3758 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3759 ((params)->fromCapabilities & (flag)) && \
3760 (((params)->toCapabilities & (flag)) == 0))
3761
3762 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3763 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3764 ((params)->toCapabilities & (flag)) && \
3765 (((params)->fromCapabilities & (flag)) == 0))
3766
3767 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3768 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3769 ((params)->fromCapabilities & (flag)) && \
3770 (((params)->toCapabilities & (flag)) == 0))
3771
3772 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3773 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3774 ((params)->toCapabilities & (flag)) && \
3775 (((params)->fromCapabilities & (flag)) == 0))
3776
3777 //******************************************************************************
3778 // sysPowerDownHandler
3779 //
3780 // Perform a vfs sync before system sleep.
3781 //******************************************************************************
3782
3783 IOReturn
sysPowerDownHandler(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgs,vm_size_t argSize)3784 IOPMrootDomain::sysPowerDownHandler(
3785 void * target, void * refCon,
3786 UInt32 messageType, IOService * service,
3787 void * messageArgs, vm_size_t argSize )
3788 {
3789 static UInt32 lastSystemMessageType = 0;
3790 IOReturn ret = 0;
3791
3792 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3793
3794 // rdar://problem/50363791
3795 // Sanity check to make sure the SystemWill/Has message types are
3796 // received in the expected order for all kernel priority clients.
3797 if (messageType == kIOMessageSystemWillSleep ||
3798 messageType == kIOMessageSystemWillPowerOn ||
3799 messageType == kIOMessageSystemHasPoweredOn) {
3800 switch (messageType) {
3801 case kIOMessageSystemWillPowerOn:
3802 assert(lastSystemMessageType == kIOMessageSystemWillSleep);
3803 break;
3804 case kIOMessageSystemHasPoweredOn:
3805 assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3806 break;
3807 }
3808
3809 lastSystemMessageType = messageType;
3810 }
3811
3812 if (!gRootDomain) {
3813 return kIOReturnUnsupported;
3814 }
3815
3816 if (messageType == kIOMessageSystemCapabilityChange) {
3817 IOPMSystemCapabilityChangeParameters * params =
3818 (IOPMSystemCapabilityChangeParameters *) messageArgs;
3819
3820 // Interested applications have been notified of an impending power
3821 // change and have acked (when applicable).
3822 // This is our chance to save whatever state we can before powering
3823 // down.
3824 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3825 // via callout
3826
3827 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3828 params->fromCapabilities, params->toCapabilities,
3829 params->changeFlags);
3830
3831 if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3832 // We will ack within 20 seconds
3833 params->maxWaitForReply = 20 * 1000 * 1000;
3834
3835 #if HIBERNATION
3836 gRootDomain->evaluateSystemSleepPolicyEarly();
3837
3838 // add in time we could spend freeing pages
3839 if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3840 params->maxWaitForReply = kCapabilityClientMaxWait;
3841 }
3842 DLOG("sysPowerDownHandler max wait %d s\n",
3843 (int) (params->maxWaitForReply / 1000 / 1000));
3844 #endif
3845
3846 // Notify platform that sleep has begun, after the early
3847 // sleep policy evaluation.
3848 getPlatform()->callPlatformFunction(
3849 sleepMessagePEFunction.get(), false,
3850 (void *)(uintptr_t) kIOMessageSystemWillSleep,
3851 NULL, NULL, NULL);
3852
3853 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3854 // Purposely delay the ack and hope that shutdown occurs quickly.
3855 // Another option is not to schedule the thread and wait for
3856 // ack timeout...
3857 AbsoluteTime deadline;
3858 clock_interval_to_deadline( 30, kSecondScale, &deadline );
3859 thread_call_enter1_delayed(
3860 gRootDomain->diskSyncCalloutEntry,
3861 (thread_call_param_t)(uintptr_t) params->notifyRef,
3862 deadline );
3863 } else {
3864 thread_call_enter1(
3865 gRootDomain->diskSyncCalloutEntry,
3866 (thread_call_param_t)(uintptr_t) params->notifyRef);
3867 }
3868 }
3869 #if HIBERNATION
3870 else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
3871 // We will ack within 110 seconds
3872 params->maxWaitForReply = 110 * 1000 * 1000;
3873
3874 thread_call_enter1(
3875 gRootDomain->diskSyncCalloutEntry,
3876 (thread_call_param_t)(uintptr_t) params->notifyRef);
3877 }
3878 #endif
3879 ret = kIOReturnSuccess;
3880 }
3881
3882 return ret;
3883 }
3884
3885 //******************************************************************************
3886 // handleQueueSleepWakeUUID
3887 //
3888 // Called from IOPMrootDomain when we're initiating a sleep,
3889 // or indirectly from PM configd when PM decides to clear the UUID.
3890 // PM clears the UUID several minutes after successful wake from sleep,
3891 // so that we might associate App spindumps with the immediately previous
3892 // sleep/wake.
3893 //
3894 // @param obj has a retain on it. We're responsible for releasing that retain.
3895 //******************************************************************************
3896
3897 void
handleQueueSleepWakeUUID(OSObject * obj)3898 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
3899 {
3900 OSSharedPtr<OSString> str;
3901
3902 if (kOSBooleanFalse == obj) {
3903 handlePublishSleepWakeUUID(false);
3904 } else {
3905 str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
3906 if (str) {
3907 // This branch caches the UUID for an upcoming sleep/wake
3908 queuedSleepWakeUUIDString = str;
3909 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
3910 }
3911 }
3912 }
3913 //******************************************************************************
3914 // handlePublishSleepWakeUUID
3915 //
3916 // Called from IOPMrootDomain when we're initiating a sleep,
3917 // or indirectly from PM configd when PM decides to clear the UUID.
3918 // PM clears the UUID several minutes after successful wake from sleep,
3919 // so that we might associate App spindumps with the immediately previous
3920 // sleep/wake.
3921 //******************************************************************************
3922
3923 void
handlePublishSleepWakeUUID(bool shouldPublish)3924 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
3925 {
3926 ASSERT_GATED();
3927
3928 /*
3929 * Clear the current UUID
3930 */
3931 if (gSleepWakeUUIDIsSet) {
3932 DLOG("SleepWake UUID cleared\n");
3933
3934 gSleepWakeUUIDIsSet = false;
3935
3936 removeProperty(kIOPMSleepWakeUUIDKey);
3937 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
3938 }
3939
3940 /*
3941 * Optionally, publish a new UUID
3942 */
3943 if (queuedSleepWakeUUIDString && shouldPublish) {
3944 OSSharedPtr<OSString> publishThisUUID;
3945
3946 publishThisUUID = queuedSleepWakeUUIDString;
3947
3948 if (publishThisUUID) {
3949 setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
3950 }
3951
3952 gSleepWakeUUIDIsSet = true;
3953 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
3954
3955 queuedSleepWakeUUIDString.reset();
3956 }
3957 }
3958
3959 //******************************************************************************
3960 // IOPMGetSleepWakeUUIDKey
3961 //
3962 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3963 // To get the full key -- a C string -- the buffer must large enough for
3964 // the end-of-string character.
3965 // The key is expected to be an UUID string
3966 //******************************************************************************
3967
3968 extern "C" bool
IOPMCopySleepWakeUUIDKey(char * buffer,size_t buf_len)3969 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
3970 {
3971 if (!gSleepWakeUUIDIsSet) {
3972 return false;
3973 }
3974
3975 if (buffer != NULL) {
3976 OSSharedPtr<OSString> string =
3977 OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
3978
3979 if (!string) {
3980 *buffer = '\0';
3981 } else {
3982 strlcpy(buffer, string->getCStringNoCopy(), buf_len);
3983 }
3984 }
3985
3986 return true;
3987 }
3988
3989 //******************************************************************************
3990 // lowLatencyAudioNotify
3991 //
3992 // Used to send an update about low latency audio activity to interested
3993 // clients. To keep the overhead minimal the OSDictionary used here
3994 // is initialized at boot.
3995 //******************************************************************************
3996
3997 void
lowLatencyAudioNotify(uint64_t time,boolean_t state)3998 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
3999 {
4000 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
4001 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
4002 lowLatencyAudioNotifyTimestampVal->setValue(time);
4003 lowLatencyAudioNotifyStateVal->setValue(state);
4004 setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
4005 } else {
4006 DLOG("LowLatencyAudioNotify error\n");
4007 }
4008 return;
4009 }
4010
4011 //******************************************************************************
4012 // IOPMrootDomainRTNotifier
4013 //
4014 // Used by performance controller to update the timestamp and state associated
4015 // with low latency audio activity in the system.
4016 //******************************************************************************
4017
4018 extern "C" void
IOPMrootDomainRTNotifier(uint64_t time,boolean_t state)4019 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
4020 {
4021 gRootDomain->lowLatencyAudioNotify(time, state);
4022 return;
4023 }
4024
4025 //******************************************************************************
4026 // initializeBootSessionUUID
4027 //
4028 // Initialize the boot session uuid at boot up and sets it into registry.
4029 //******************************************************************************
4030
4031 void
initializeBootSessionUUID(void)4032 IOPMrootDomain::initializeBootSessionUUID(void)
4033 {
4034 uuid_t new_uuid;
4035 uuid_string_t new_uuid_string;
4036
4037 uuid_generate(new_uuid);
4038 uuid_unparse_upper(new_uuid, new_uuid_string);
4039 memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
4040
4041 setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
4042 }
4043
4044 //******************************************************************************
4045 // Root domain uses the private and tagged changePowerState methods for
4046 // tracking and logging purposes.
4047 //******************************************************************************
4048
4049 #define REQUEST_TAG_TO_REASON(x) ((uint16_t)x)
4050
4051 static uint32_t
nextRequestTag(IOPMRequestTag tag)4052 nextRequestTag( IOPMRequestTag tag )
4053 {
4054 static SInt16 msb16 = 1;
4055 uint16_t id = OSAddAtomic16(1, &msb16);
4056 return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
4057 }
4058
4059 // TODO: remove this shim function and exported symbol
4060 IOReturn
changePowerStateTo(unsigned long ordinal)4061 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
4062 {
4063 return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
4064 }
4065
4066 // TODO: remove this shim function and exported symbol
4067 IOReturn
changePowerStateToPriv(unsigned long ordinal)4068 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
4069 {
4070 return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
4071 }
4072
4073 IOReturn
changePowerStateWithOverrideTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4074 IOPMrootDomain::changePowerStateWithOverrideTo(
4075 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4076 {
4077 uint32_t tag = nextRequestTag(reason);
4078 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4079
4080 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4081 return kIOReturnUnsupported;
4082 }
4083
4084 return super::changePowerStateWithOverrideTo(ordinal, tag);
4085 }
4086
4087 IOReturn
changePowerStateWithTagTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4088 IOPMrootDomain::changePowerStateWithTagTo(
4089 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4090 {
4091 uint32_t tag = nextRequestTag(reason);
4092 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4093
4094 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4095 return kIOReturnUnsupported;
4096 }
4097
4098 return super::changePowerStateWithTagTo(ordinal, tag);
4099 }
4100
4101 IOReturn
changePowerStateWithTagToPriv(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4102 IOPMrootDomain::changePowerStateWithTagToPriv(
4103 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4104 {
4105 uint32_t tag = nextRequestTag(reason);
4106 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4107
4108 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4109 return kIOReturnUnsupported;
4110 }
4111
4112 return super::changePowerStateWithTagToPriv(ordinal, tag);
4113 }
4114
4115 //******************************************************************************
4116 // activity detect
4117 //
4118 //******************************************************************************
4119
4120 bool
activitySinceSleep(void)4121 IOPMrootDomain::activitySinceSleep(void)
4122 {
4123 return userActivityCount != userActivityAtSleep;
4124 }
4125
4126 bool
abortHibernation(void)4127 IOPMrootDomain::abortHibernation(void)
4128 {
4129 #if __arm64__
4130 // don't allow hibernation to be aborted on ARM due to user activity
4131 // since once ApplePMGR decides we're hibernating, we can't turn back
4132 // see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4133 return false;
4134 #else
4135 bool ret = activitySinceSleep();
4136
4137 if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4138 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4139 hibernateAborted = true;
4140 }
4141 return ret;
4142 #endif
4143 }
4144
4145 extern "C" int
hibernate_should_abort(void)4146 hibernate_should_abort(void)
4147 {
4148 if (gRootDomain) {
4149 return gRootDomain->abortHibernation();
4150 } else {
4151 return 0;
4152 }
4153 }
4154
4155 //******************************************************************************
4156 // scheduleImmediateDebugWake
4157 //
4158 // Schedule a wake with RTC to wake us back up immediately after we sleep.
4159 // Useful when a cancel request comes in past the revert point on the sleep path
4160 //******************************************************************************
4161
4162 void
scheduleImmediateDebugWake(void)4163 IOPMrootDomain::scheduleImmediateDebugWake( void )
4164 {
4165 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(1);
4166 OSSharedPtr<OSNumber> secs = OSNumber::withNumber(1, 32);
4167
4168 if (dict && secs) {
4169 dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4170 gRootDomain->setProperties(dict.get());
4171 MSG("Reverting sleep with relative wake\n");
4172 }
4173 }
4174
4175 //******************************************************************************
4176 // willNotifyPowerChildren
4177 //
4178 // Called after all interested drivers have all acknowledged the power change,
4179 // but before any power children is informed. Dispatched though a thread call,
4180 // so it is safe to perform work that might block on a sleeping disk. PM state
4181 // machine (not thread) will block w/o timeout until this function returns.
4182 //******************************************************************************
4183
4184 void
willNotifyPowerChildren(IOPMPowerStateIndex newPowerState)4185 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4186 {
4187 if (SLEEP_STATE == newPowerState) {
4188 notifierThread = current_thread();
4189 if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
4190 AbsoluteTime deadline;
4191
4192 clock_interval_to_deadline(10, kSecondScale, &deadline);
4193 #if defined(XNU_TARGET_OS_OSX)
4194 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
4195 #endif /* defined(XNU_TARGET_OS_OSX) */
4196 }
4197
4198 _aotReadyToFullWake = false;
4199 #if 0
4200 if (_aotLingerTime) {
4201 uint64_t deadline;
4202 IOLog("aot linger no return\n");
4203 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
4204 clock_delay_until(deadline);
4205 }
4206 #endif
4207 if (!_aotMode) {
4208 _aotTestTime = 0;
4209 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4210 _aotLastWakeTime = 0;
4211 if (_aotMetrics) {
4212 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4213 }
4214 } else if (!_aotNow && !_debugWakeSeconds) {
4215 _aotNow = true;
4216 _aotPendingFlags = 0;
4217 _aotTasksSuspended = true;
4218 _aotLastWakeTime = 0;
4219 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4220 if (kIOPMAOTModeCycle & _aotMode) {
4221 clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
4222 _aotTestTime = mach_continuous_time() + _aotTestInterval;
4223 setWakeTime(_aotTestTime);
4224 }
4225 uint32_t lingerSecs;
4226 if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
4227 lingerSecs = 0;
4228 }
4229 clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
4230 clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
4231 clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
4232 }
4233
4234 #if HIBERNATION
4235 IOHibernateSystemSleep();
4236 IOHibernateIOKitSleep();
4237 #endif
4238 #if defined(__arm64__) && HIBERNATION
4239 // On AS, hibernation cannot be aborted. Resetting RTC to 1s during hibernation upon detecting
4240 // user activity is pointless (we are likely to spend >1s hibernating). It also clears existing
4241 // alarms, which can mess with cycler tools.
4242 if (gRootDomain->activitySinceSleep() && gIOHibernateState == kIOHibernateStateInactive) {
4243 #else /* defined(__arm64__) && HIBERNATION */
4244 // On non-AS, hibernation can be aborted if user activity is detected. So continue to reset the
4245 // RTC alarm (even during hibernation) so we can immediately wake from regular S2R if needed.
4246 if (gRootDomain->activitySinceSleep()) {
4247 #endif /* defined(__arm64__) && HIBERNATION */
4248 scheduleImmediateDebugWake();
4249 }
4250
4251 notifierThread = NULL;
4252 }
4253 }
4254
4255 //******************************************************************************
4256 // willTellSystemCapabilityDidChange
4257 //
4258 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4259 // domain is raising its power state, immediately after notifying interested
4260 // drivers and power children.
4261 //******************************************************************************
4262
4263 void
4264 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4265 {
4266 if ((_systemTransitionType == kSystemTransitionWake) &&
4267 !CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
4268 // After powering up drivers, dark->full promotion on the current wake
4269 // transition is no longer possible. That is because the next machine
4270 // state will issue the system capability change messages.
4271 // The darkWakePowerClamped flag may already be set if the system has
4272 // at least one driver that was power clamped due to dark wake.
4273 // This function sets the darkWakePowerClamped flag in case there
4274 // is no power-clamped driver in the system.
4275 //
4276 // Last opportunity to exit dark wake using:
4277 // requestFullWake( kFullWakeReasonLocalUser );
4278
4279 if (!darkWakePowerClamped) {
4280 if (darkWakeLogClamp) {
4281 AbsoluteTime now;
4282 uint64_t nsec;
4283
4284 clock_get_uptime(&now);
4285 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
4286 absolutetime_to_nanoseconds(now, &nsec);
4287 DLOG("dark wake promotion disabled at %u ms\n",
4288 ((int)((nsec) / NSEC_PER_MSEC)));
4289 }
4290 darkWakePowerClamped = true;
4291 }
4292 }
4293 }
4294
4295 //******************************************************************************
4296 // sleepOnClamshellClosed
4297 //
4298 // contains the logic to determine if the system should sleep when the clamshell
4299 // is closed.
4300 //******************************************************************************
4301
4302 bool
4303 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4304 {
4305 if (!clamshellExists) {
4306 return false;
4307 }
4308
4309 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4310 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4311
4312 return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4313 }
4314
4315 bool
4316 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4317 {
4318 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4319 // closed && battery
4320 if (!clamshellExists) {
4321 return false;
4322 }
4323
4324 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4325 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4326
4327 return !acAdaptorConnected && !clamshellSleepDisableMask;
4328 }
4329
4330 void
4331 IOPMrootDomain::sendClientClamshellNotification( void )
4332 {
4333 /* Only broadcast clamshell alert if clamshell exists. */
4334 if (!clamshellExists) {
4335 return;
4336 }
4337
4338 setProperty(kAppleClamshellStateKey,
4339 clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4340
4341 setProperty(kAppleClamshellCausesSleepKey,
4342 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4343
4344 /* Argument to message is a bitfiel of
4345 * ( kClamshellStateBit | kClamshellSleepBit )
4346 */
4347 messageClients(kIOPMMessageClamshellStateChange,
4348 (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4349 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4350 }
4351
4352 //******************************************************************************
4353 // getSleepSupported
4354 //
4355 // Deprecated
4356 //******************************************************************************
4357
4358 IOOptionBits
4359 IOPMrootDomain::getSleepSupported( void )
4360 {
4361 return platformSleepSupport;
4362 }
4363
4364 //******************************************************************************
4365 // setSleepSupported
4366 //
4367 // Deprecated
4368 //******************************************************************************
4369
4370 void
4371 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4372 {
4373 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4374 OSBitOrAtomic(flags, &platformSleepSupport);
4375 }
4376
4377 //******************************************************************************
4378 // setClamShellSleepDisable
4379 //
4380 //******************************************************************************
4381
4382 void
4383 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4384 {
4385 uint32_t oldMask;
4386
4387 // User client calls this in non-gated context
4388 if (gIOPMWorkLoop->inGate() == false) {
4389 gIOPMWorkLoop->runAction(
4390 OSMemberFunctionCast(IOWorkLoop::Action, this,
4391 &IOPMrootDomain::setClamShellSleepDisable),
4392 (OSObject *) this,
4393 (void *) disable, (void *)(uintptr_t) bitmask);
4394 return;
4395 }
4396
4397 oldMask = clamshellSleepDisableMask;
4398 if (disable) {
4399 clamshellSleepDisableMask |= bitmask;
4400 } else {
4401 clamshellSleepDisableMask &= ~bitmask;
4402 }
4403 DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4404
4405 if (clamshellExists && clamshellClosed &&
4406 (clamshellSleepDisableMask != oldMask) &&
4407 (clamshellSleepDisableMask == 0)) {
4408 handlePowerNotification(kLocalEvalClamshellCommand);
4409 }
4410 }
4411
4412 //******************************************************************************
4413 // wakeFromDoze
4414 //
4415 // Deprecated.
4416 //******************************************************************************
4417
4418 void
4419 IOPMrootDomain::wakeFromDoze( void )
4420 {
4421 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4422 }
4423
4424 //******************************************************************************
4425 // recordRTCAlarm
4426 //
4427 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4428 // should be a dark wake or a full wake. Both Maintenance and SleepService
4429 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4430 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4431 // PMSettings are ignored.
4432 //
4433 // Caller serialized using settingsCtrlLock.
4434 //******************************************************************************
4435
4436 void
4437 IOPMrootDomain::recordRTCAlarm(
4438 const OSSymbol *type,
4439 OSObject *object )
4440 {
4441 uint32_t previousAlarmMask = _scheduledAlarmMask;
4442
4443 if (type == gIOPMSettingDebugWakeRelativeKey) {
4444 OSNumber * n = OSDynamicCast(OSNumber, object);
4445 if (n) {
4446 // Debug wake has highest scheduling priority so it overrides any
4447 // pre-existing alarm.
4448 uint32_t debugSecs = n->unsigned32BitValue();
4449 _nextScheduledAlarmType.reset(type, OSRetain);
4450 _nextScheduledAlarmUTC = debugSecs;
4451
4452 _debugWakeSeconds = debugSecs;
4453 OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4454 DLOG("next alarm (%s) in %u secs\n",
4455 type->getCStringNoCopy(), debugSecs);
4456 }
4457 } else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) ||
4458 (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) ||
4459 (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) {
4460 OSData * data = OSDynamicCast(OSData, object);
4461 if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) {
4462 const IOPMCalendarStruct * cs;
4463 bool replaceNextAlarm = false;
4464 clock_sec_t secs;
4465
4466 cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4467 secs = IOPMConvertCalendarToSeconds(cs);
4468 DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4469
4470 // Update the next scheduled alarm type
4471 if ((_nextScheduledAlarmType == NULL) ||
4472 ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4473 (secs < _nextScheduledAlarmUTC))) {
4474 replaceNextAlarm = true;
4475 }
4476
4477 if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4478 if (cs->year) {
4479 _calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4480 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4481 } else {
4482 // TODO: can this else-block be removed?
4483 _calendarWakeAlarmUTC = 0;
4484 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4485 }
4486 }
4487 if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4488 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4489 }
4490 if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4491 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4492 }
4493
4494 if (replaceNextAlarm) {
4495 _nextScheduledAlarmType.reset(type, OSRetain);
4496 _nextScheduledAlarmUTC = secs;
4497 DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4498 }
4499 }
4500 }
4501
4502 if (_scheduledAlarmMask != previousAlarmMask) {
4503 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4504 }
4505 }
4506
4507 // MARK: -
4508 // MARK: Features
4509
4510 //******************************************************************************
4511 // publishFeature
4512 //
4513 // Adds a new feature to the supported features dictionary
4514 //******************************************************************************
4515
4516 void
4517 IOPMrootDomain::publishFeature( const char * feature )
4518 {
4519 publishFeature(feature, kRD_AllPowerSources, NULL);
4520 }
4521
4522 //******************************************************************************
4523 // publishFeature (with supported power source specified)
4524 //
4525 // Adds a new feature to the supported features dictionary
4526 //******************************************************************************
4527
4528 void
4529 IOPMrootDomain::publishFeature(
4530 const char *feature,
4531 uint32_t supportedWhere,
4532 uint32_t *uniqueFeatureID)
4533 {
4534 static uint16_t next_feature_id = 500;
4535
4536 OSSharedPtr<OSNumber> new_feature_data;
4537 OSNumber *existing_feature = NULL;
4538 OSArray *existing_feature_arr_raw = NULL;
4539 OSSharedPtr<OSArray> existing_feature_arr;
4540 OSObject *osObj = NULL;
4541 uint32_t feature_value = 0;
4542
4543 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4544
4545 if (!supportedWhere) {
4546 // Feature isn't supported anywhere!
4547 return;
4548 }
4549
4550 if (next_feature_id > 5000) {
4551 // Far, far too many features!
4552 return;
4553 }
4554
4555 if (featuresDictLock) {
4556 IOLockLock(featuresDictLock);
4557 }
4558
4559 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4560 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4561 OSSharedPtr<OSDictionary> features;
4562
4563 // Create new features dict if necessary
4564 if (origFeatures) {
4565 features = OSDictionary::withDictionary(origFeatures);
4566 } else {
4567 features = OSDictionary::withCapacity(1);
4568 }
4569
4570 // Create OSNumber to track new feature
4571
4572 next_feature_id += 1;
4573 if (uniqueFeatureID) {
4574 // We don't really mind if the calling kext didn't give us a place
4575 // to stash their unique id. Many kexts don't plan to unload, and thus
4576 // have no need to remove themselves later.
4577 *uniqueFeatureID = next_feature_id;
4578 }
4579
4580 feature_value = (uint32_t)next_feature_id;
4581 feature_value <<= 16;
4582 feature_value += supportedWhere;
4583
4584 new_feature_data = OSNumber::withNumber(
4585 (unsigned long long)feature_value, 32);
4586
4587 // Does features object already exist?
4588 if ((osObj = features->getObject(feature))) {
4589 if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
4590 // We need to create an OSArray to hold the now 2 elements.
4591 existing_feature_arr = OSArray::withObjects(
4592 (const OSObject **)&existing_feature, 1, 2);
4593 } else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) {
4594 // Add object to existing array
4595 existing_feature_arr = OSArray::withArray(
4596 existing_feature_arr_raw,
4597 existing_feature_arr_raw->getCount() + 1);
4598 }
4599
4600 if (existing_feature_arr) {
4601 existing_feature_arr->setObject(new_feature_data.get());
4602 features->setObject(feature, existing_feature_arr.get());
4603 }
4604 } else {
4605 // The easy case: no previously existing features listed. We simply
4606 // set the OSNumber at key 'feature' and we're on our way.
4607 features->setObject(feature, new_feature_data.get());
4608 }
4609
4610 setProperty(kRootDomainSupportedFeatures, features.get());
4611
4612 if (featuresDictLock) {
4613 IOLockUnlock(featuresDictLock);
4614 }
4615
4616 // Notify EnergySaver and all those in user space so they might
4617 // re-populate their feature specific UI
4618 if (pmPowerStateQueue) {
4619 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4620 }
4621 }
4622
4623 //******************************************************************************
4624 // removePublishedFeature
4625 //
4626 // Removes previously published feature
4627 //******************************************************************************
4628
4629 IOReturn
4630 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4631 {
4632 IOReturn ret = kIOReturnError;
4633 uint32_t feature_value = 0;
4634 uint16_t feature_id = 0;
4635 bool madeAChange = false;
4636
4637 OSSymbol *dictKey = NULL;
4638 OSSharedPtr<OSCollectionIterator> dictIterator;
4639 OSArray *arrayMember = NULL;
4640 OSNumber *numberMember = NULL;
4641 OSObject *osObj = NULL;
4642 OSNumber *osNum = NULL;
4643 OSSharedPtr<OSArray> arrayMemberCopy;
4644
4645 if (kBadPMFeatureID == removeFeatureID) {
4646 return kIOReturnNotFound;
4647 }
4648
4649 if (featuresDictLock) {
4650 IOLockLock(featuresDictLock);
4651 }
4652
4653 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4654 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4655 OSSharedPtr<OSDictionary> features;
4656
4657 if (origFeatures) {
4658 // Any modifications to the dictionary are made to the copy to prevent
4659 // races & crashes with userland clients. Dictionary updated
4660 // automically later.
4661 features = OSDictionary::withDictionary(origFeatures);
4662 } else {
4663 features = NULL;
4664 ret = kIOReturnNotFound;
4665 goto exit;
4666 }
4667
4668 // We iterate 'features' dictionary looking for an entry tagged
4669 // with 'removeFeatureID'. If found, we remove it from our tracking
4670 // structures and notify the OS via a general interest message.
4671
4672 dictIterator = OSCollectionIterator::withCollection(features.get());
4673 if (!dictIterator) {
4674 goto exit;
4675 }
4676
4677 while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4678 osObj = features->getObject(dictKey);
4679
4680 // Each Feature is either tracked by an OSNumber
4681 if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
4682 feature_value = numberMember->unsigned32BitValue();
4683 feature_id = (uint16_t)(feature_value >> 16);
4684
4685 if (feature_id == (uint16_t)removeFeatureID) {
4686 // Remove this node
4687 features->removeObject(dictKey);
4688 madeAChange = true;
4689 break;
4690 }
4691
4692 // Or tracked by an OSArray of OSNumbers
4693 } else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4694 unsigned int arrayCount = arrayMember->getCount();
4695
4696 for (unsigned int i = 0; i < arrayCount; i++) {
4697 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4698 if (!osNum) {
4699 continue;
4700 }
4701
4702 feature_value = osNum->unsigned32BitValue();
4703 feature_id = (uint16_t)(feature_value >> 16);
4704
4705 if (feature_id == (uint16_t)removeFeatureID) {
4706 // Remove this node
4707 if (1 == arrayCount) {
4708 // If the array only contains one element, remove
4709 // the whole thing.
4710 features->removeObject(dictKey);
4711 } else {
4712 // Otherwise remove the element from a copy of the array.
4713 arrayMemberCopy = OSArray::withArray(arrayMember);
4714 if (arrayMemberCopy) {
4715 arrayMemberCopy->removeObject(i);
4716 features->setObject(dictKey, arrayMemberCopy.get());
4717 }
4718 }
4719
4720 madeAChange = true;
4721 break;
4722 }
4723 }
4724 }
4725 }
4726
4727 if (madeAChange) {
4728 ret = kIOReturnSuccess;
4729
4730 setProperty(kRootDomainSupportedFeatures, features.get());
4731
4732 // Notify EnergySaver and all those in user space so they might
4733 // re-populate their feature specific UI
4734 if (pmPowerStateQueue) {
4735 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4736 }
4737 } else {
4738 ret = kIOReturnNotFound;
4739 }
4740
4741 exit:
4742 if (featuresDictLock) {
4743 IOLockUnlock(featuresDictLock);
4744 }
4745 return ret;
4746 }
4747
4748 //******************************************************************************
4749 // publishPMSetting (private)
4750 //
4751 // Should only be called by PMSettingObject to publish a PM Setting as a
4752 // supported feature.
4753 //******************************************************************************
4754
4755 void
4756 IOPMrootDomain::publishPMSetting(
4757 const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4758 {
4759 if (noPublishPMSettings &&
4760 (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4761 // Setting found in noPublishPMSettings array
4762 *featureID = kBadPMFeatureID;
4763 return;
4764 }
4765
4766 publishFeature(
4767 feature->getCStringNoCopy(), where, featureID);
4768 }
4769
4770 //******************************************************************************
4771 // setPMSetting (private)
4772 //
4773 // Internal helper to relay PM settings changes from user space to individual
4774 // drivers. Should be called only by IOPMrootDomain::setProperties.
4775 //******************************************************************************
4776
4777 IOReturn
4778 IOPMrootDomain::setPMSetting(
4779 const OSSymbol *type,
4780 OSObject *object )
4781 {
4782 PMSettingCallEntry *entries = NULL;
4783 OSSharedPtr<OSArray> chosen;
4784 const OSArray *array;
4785 PMSettingObject *pmso;
4786 thread_t thisThread;
4787 int i, j, count, capacity;
4788 bool ok = false;
4789 IOReturn ret;
4790
4791 if (NULL == type) {
4792 return kIOReturnBadArgument;
4793 }
4794
4795 PMSETTING_LOCK();
4796
4797 // Update settings dict so changes are visible from copyPMSetting().
4798 fPMSettingsDict->setObject(type, object);
4799
4800 // Prep all PMSetting objects with the given 'type' for callout.
4801 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
4802 if (!array || ((capacity = array->getCount()) == 0)) {
4803 goto unlock_exit;
4804 }
4805
4806 // Array to retain PMSetting objects targeted for callout.
4807 chosen = OSArray::withCapacity(capacity);
4808 if (!chosen) {
4809 goto unlock_exit; // error
4810 }
4811 entries = IONew(PMSettingCallEntry, capacity);
4812 if (!entries) {
4813 goto unlock_exit; // error
4814 }
4815 memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4816
4817 thisThread = current_thread();
4818
4819 for (i = 0, j = 0; i < capacity; i++) {
4820 pmso = (PMSettingObject *) array->getObject(i);
4821 if (pmso->disabled) {
4822 continue;
4823 }
4824 entries[j].thread = thisThread;
4825 queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4826 chosen->setObject(pmso);
4827 j++;
4828 }
4829 count = j;
4830 if (!count) {
4831 goto unlock_exit;
4832 }
4833
4834 PMSETTING_UNLOCK();
4835
4836 // Call each pmso in the chosen array.
4837 for (i = 0; i < count; i++) {
4838 pmso = (PMSettingObject *) chosen->getObject(i);
4839 ret = pmso->dispatchPMSetting(type, object);
4840 if (ret == kIOReturnSuccess) {
4841 // At least one setting handler was successful
4842 ok = true;
4843 #if DEVELOPMENT || DEBUG
4844 } else {
4845 // Log the handler and kext that failed
4846 OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
4847 if (kextName) {
4848 DLOG("PMSetting(%s) error 0x%x from %s\n",
4849 type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
4850 }
4851 #endif
4852 }
4853 }
4854
4855 PMSETTING_LOCK();
4856 for (i = 0; i < count; i++) {
4857 pmso = (PMSettingObject *) chosen->getObject(i);
4858 queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
4859 if (pmso->waitThread) {
4860 PMSETTING_WAKEUP(pmso);
4861 }
4862 }
4863
4864 if (ok) {
4865 recordRTCAlarm(type, object);
4866 }
4867 unlock_exit:
4868 PMSETTING_UNLOCK();
4869
4870 if (entries) {
4871 IODelete(entries, PMSettingCallEntry, capacity);
4872 }
4873
4874 return kIOReturnSuccess;
4875 }
4876
4877 //******************************************************************************
4878 // copyPMSetting (public)
4879 //
4880 // Allows kexts to safely read setting values, without being subscribed to
4881 // notifications.
4882 //******************************************************************************
4883
4884 OSSharedPtr<OSObject>
4885 IOPMrootDomain::copyPMSetting(
4886 OSSymbol *whichSetting)
4887 {
4888 OSSharedPtr<OSObject> obj;
4889
4890 if (!whichSetting) {
4891 return NULL;
4892 }
4893
4894 PMSETTING_LOCK();
4895 obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
4896 PMSETTING_UNLOCK();
4897
4898 return obj;
4899 }
4900
4901 //******************************************************************************
4902 // registerPMSettingController (public)
4903 //
4904 // direct wrapper to registerPMSettingController with uint32_t power source arg
4905 //******************************************************************************
4906
4907 IOReturn
4908 IOPMrootDomain::registerPMSettingController(
4909 const OSSymbol * settings[],
4910 IOPMSettingControllerCallback func,
4911 OSObject *target,
4912 uintptr_t refcon,
4913 OSObject **handle)
4914 {
4915 return registerPMSettingController(
4916 settings,
4917 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
4918 func, target, refcon, handle);
4919 }
4920
4921 //******************************************************************************
4922 // registerPMSettingController (public)
4923 //
4924 // Kexts may register for notifications when a particular setting is changed.
4925 // A list of settings is available in IOPM.h.
4926 // Arguments:
4927 // * settings - An OSArray containing OSSymbols. Caller should populate this
4928 // array with a list of settings caller wants notifications from.
4929 // * func - A C function callback of the type IOPMSettingControllerCallback
4930 // * target - caller may provide an OSObject *, which PM will pass as an
4931 // target to calls to "func"
4932 // * refcon - caller may provide an void *, which PM will pass as an
4933 // argument to calls to "func"
4934 // * handle - This is a return argument. We will populate this pointer upon
4935 // call success. Hold onto this and pass this argument to
4936 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4937 // Returns:
4938 // kIOReturnSuccess on success
4939 //******************************************************************************
4940
4941 IOReturn
4942 IOPMrootDomain::registerPMSettingController(
4943 const OSSymbol * settings[],
4944 uint32_t supportedPowerSources,
4945 IOPMSettingControllerCallback func,
4946 OSObject *target,
4947 uintptr_t refcon,
4948 OSObject **handle)
4949 {
4950 PMSettingObject *pmso = NULL;
4951 OSObject *pmsh = NULL;
4952 int i;
4953
4954 if (NULL == settings ||
4955 NULL == func ||
4956 NULL == handle) {
4957 return kIOReturnBadArgument;
4958 }
4959
4960 pmso = PMSettingObject::pmSettingObject(
4961 (IOPMrootDomain *) this, func, target,
4962 refcon, supportedPowerSources, settings, &pmsh);
4963
4964 if (!pmso) {
4965 *handle = NULL;
4966 return kIOReturnInternalError;
4967 }
4968
4969 PMSETTING_LOCK();
4970 for (i = 0; settings[i]; i++) {
4971 OSSharedPtr<OSArray> newList;
4972 OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
4973 if (!list) {
4974 // New array of callbacks for this setting
4975 newList = OSArray::withCapacity(1);
4976 settingsCallbacks->setObject(settings[i], newList.get());
4977 list = newList.get();
4978 }
4979
4980 // Add caller to the callback list
4981 list->setObject(pmso);
4982 }
4983 PMSETTING_UNLOCK();
4984
4985 // Return handle to the caller, the setting object is private.
4986 *handle = pmsh;
4987
4988 return kIOReturnSuccess;
4989 }
4990
4991 //******************************************************************************
4992 // deregisterPMSettingObject (private)
4993 //
4994 // Only called from PMSettingObject.
4995 //******************************************************************************
4996
4997 void
4998 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
4999 {
5000 thread_t thisThread = current_thread();
5001 PMSettingCallEntry *callEntry;
5002 OSSharedPtr<OSCollectionIterator> iter;
5003 OSSymbol *sym;
5004 OSArray *array;
5005 int index;
5006 bool wait;
5007
5008 PMSETTING_LOCK();
5009
5010 pmso->disabled = true;
5011
5012 // Wait for all callout threads to finish.
5013 do {
5014 wait = false;
5015 queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
5016 {
5017 if (callEntry->thread != thisThread) {
5018 wait = true;
5019 break;
5020 }
5021 }
5022 if (wait) {
5023 assert(NULL == pmso->waitThread);
5024 pmso->waitThread = thisThread;
5025 PMSETTING_WAIT(pmso);
5026 pmso->waitThread = NULL;
5027 }
5028 } while (wait);
5029
5030 // Search each PM settings array in the kernel.
5031 iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
5032 if (iter) {
5033 while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
5034 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
5035 index = array->getNextIndexOfObject(pmso, 0);
5036 if (-1 != index) {
5037 array->removeObject(index);
5038 }
5039 }
5040 }
5041
5042 PMSETTING_UNLOCK();
5043
5044 pmso->release();
5045 }
5046
5047 //******************************************************************************
5048 // informCPUStateChange
5049 //
5050 // Call into PM CPU code so that CPU power savings may dynamically adjust for
5051 // running on battery, with the lid closed, etc.
5052 //
5053 // informCPUStateChange is a no-op on non x86 systems
5054 // only x86 has explicit support in the IntelCPUPowerManagement kext
5055 //******************************************************************************
5056
5057 void
5058 IOPMrootDomain::informCPUStateChange(
5059 uint32_t type,
5060 uint32_t value )
5061 {
5062 #if defined(__i386__) || defined(__x86_64__)
5063
5064 pmioctlVariableInfo_t varInfoStruct;
5065 int pmCPUret = 0;
5066 const char *varNameStr = NULL;
5067 int32_t *varIndex = NULL;
5068
5069 if (kInformAC == type) {
5070 varNameStr = kIOPMRootDomainBatPowerCString;
5071 varIndex = &idxPMCPULimitedPower;
5072 } else if (kInformLid == type) {
5073 varNameStr = kIOPMRootDomainLidCloseCString;
5074 varIndex = &idxPMCPUClamshell;
5075 } else {
5076 return;
5077 }
5078
5079 // Set the new value!
5080 // pmCPUControl will assign us a new ID if one doesn't exist yet
5081 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
5082 varInfoStruct.varID = *varIndex;
5083 varInfoStruct.varType = vBool;
5084 varInfoStruct.varInitValue = value;
5085 varInfoStruct.varCurValue = value;
5086 strlcpy((char *)varInfoStruct.varName,
5087 (const char *)varNameStr,
5088 sizeof(varInfoStruct.varName));
5089
5090 // Set!
5091 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
5092
5093 // pmCPU only assigns numerical id's when a new varName is specified
5094 if ((0 == pmCPUret)
5095 && (*varIndex == kCPUUnknownIndex)) {
5096 // pmCPUControl has assigned us a new variable ID.
5097 // Let's re-read the structure we just SET to learn that ID.
5098 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
5099
5100 if (0 == pmCPUret) {
5101 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5102 *varIndex = varInfoStruct.varID;
5103 }
5104 }
5105
5106 return;
5107
5108 #endif /* __i386__ || __x86_64__ */
5109 }
5110
5111 // MARK: -
5112 // MARK: Deep Sleep Policy
5113
5114 #if HIBERNATION
5115
5116 //******************************************************************************
5117 // evaluateSystemSleepPolicy
5118 //******************************************************************************
5119
5120 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
5121
5122 // Sleep flags
5123 enum {
5124 kIOPMSleepFlagHibernate = 0x00000001,
5125 kIOPMSleepFlagSleepTimerEnable = 0x00000002
5126 };
5127
5128 struct IOPMSystemSleepPolicyEntry {
5129 uint32_t factorMask;
5130 uint32_t factorBits;
5131 uint32_t sleepFlags;
5132 uint32_t wakeEvents;
5133 } __attribute__((packed));
5134
5135 struct IOPMSystemSleepPolicyTable {
5136 uint32_t signature;
5137 uint16_t version;
5138 uint16_t entryCount;
5139 IOPMSystemSleepPolicyEntry entries[];
5140 } __attribute__((packed));
5141
5142 enum {
5143 kIOPMSleepAttributeHibernateSetup = 0x00000001,
5144 kIOPMSleepAttributeHibernateSleep = 0x00000002
5145 };
5146
5147 static uint32_t
5148 getSleepTypeAttributes( uint32_t sleepType )
5149 {
5150 static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5151 {
5152 /* invalid */ 0,
5153 /* abort */ 0,
5154 /* normal */ 0,
5155 /* safesleep */ kIOPMSleepAttributeHibernateSetup,
5156 /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5157 /* standby */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5158 /* poweroff */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5159 /* deepidle */ 0
5160 };
5161
5162 if (sleepType >= kIOPMSleepTypeLast) {
5163 return 0;
5164 }
5165
5166 return sleepTypeAttributes[sleepType];
5167 }
5168
5169 bool
5170 IOPMrootDomain::evaluateSystemSleepPolicy(
5171 IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5172 {
5173 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5174
5175 static const IONamedValue factorValues[] = {
5176 SLEEP_FACTOR( SleepTimerWake ),
5177 SLEEP_FACTOR( LidOpen ),
5178 SLEEP_FACTOR( ACPower ),
5179 SLEEP_FACTOR( BatteryLow ),
5180 SLEEP_FACTOR( StandbyNoDelay ),
5181 SLEEP_FACTOR( StandbyForced ),
5182 SLEEP_FACTOR( StandbyDisabled ),
5183 SLEEP_FACTOR( USBExternalDevice ),
5184 SLEEP_FACTOR( BluetoothHIDDevice ),
5185 SLEEP_FACTOR( ExternalMediaMounted ),
5186 SLEEP_FACTOR( ThunderboltDevice ),
5187 SLEEP_FACTOR( RTCAlarmScheduled ),
5188 SLEEP_FACTOR( MagicPacketWakeEnabled ),
5189 SLEEP_FACTOR( HibernateForced ),
5190 SLEEP_FACTOR( AutoPowerOffDisabled ),
5191 SLEEP_FACTOR( AutoPowerOffForced ),
5192 SLEEP_FACTOR( ExternalDisplay ),
5193 SLEEP_FACTOR( NetworkKeepAliveActive ),
5194 SLEEP_FACTOR( LocalUserActivity ),
5195 SLEEP_FACTOR( HibernateFailed ),
5196 SLEEP_FACTOR( ThermalWarning ),
5197 SLEEP_FACTOR( DisplayCaptured ),
5198 { 0, NULL }
5199 };
5200
5201 const IOPMSystemSleepPolicyTable * pt;
5202 OSSharedPtr<OSObject> prop;
5203 OSData * policyData;
5204 uint64_t currentFactors = 0;
5205 char currentFactorsBuf[512];
5206 uint32_t standbyDelay = 0;
5207 uint32_t powerOffDelay = 0;
5208 uint32_t powerOffTimer = 0;
5209 uint32_t standbyTimer = 0;
5210 uint32_t mismatch;
5211 bool standbyEnabled;
5212 bool powerOffEnabled;
5213 bool found = false;
5214
5215 // Get platform's sleep policy table
5216 if (!gSleepPolicyHandler) {
5217 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5218 if (!prop) {
5219 goto done;
5220 }
5221 }
5222
5223 // Fetch additional settings
5224 standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
5225 && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue));
5226 powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
5227 && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue));
5228 if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
5229 powerOffTimer = powerOffDelay;
5230 }
5231 if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5232 standbyTimer = standbyDelay;
5233 }
5234
5235 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5236 sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
5237 powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
5238
5239 currentFactorsBuf[0] = 0;
5240 // pmset level overrides
5241 if ((*hibMode & kIOHibernateModeOn) == 0) {
5242 if (!gSleepPolicyHandler) {
5243 standbyEnabled = false;
5244 powerOffEnabled = false;
5245 }
5246 } else if (!(*hibMode & kIOHibernateModeSleep)) {
5247 // Force hibernate (i.e. mode 25)
5248 // If standby is enabled, force standy.
5249 // If poweroff is enabled, force poweroff.
5250 if (standbyEnabled) {
5251 currentFactors |= kIOPMSleepFactorStandbyForced;
5252 } else if (powerOffEnabled) {
5253 currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
5254 } else {
5255 currentFactors |= kIOPMSleepFactorHibernateForced;
5256 }
5257 }
5258
5259 // Current factors based on environment and assertions
5260 if (sleepTimerMaintenance) {
5261 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5262 }
5263 if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5264 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5265 }
5266 if (!clamshellClosed) {
5267 currentFactors |= kIOPMSleepFactorLidOpen;
5268 }
5269 if (acAdaptorConnected) {
5270 currentFactors |= kIOPMSleepFactorACPower;
5271 }
5272 if (lowBatteryCondition) {
5273 hibernateMode = 0;
5274 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5275 if ((hibernateMode & kIOHibernateModeOn) == 0) {
5276 DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5277 } else {
5278 currentFactors |= kIOPMSleepFactorBatteryLow;
5279 }
5280 }
5281 if (!standbyDelay || !standbyTimer) {
5282 currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5283 }
5284 if (standbyNixed || !standbyEnabled) {
5285 currentFactors |= kIOPMSleepFactorStandbyDisabled;
5286 }
5287 if (resetTimers) {
5288 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5289 currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5290 }
5291 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5292 kIOPMDriverAssertionLevelOff) {
5293 currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5294 }
5295 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5296 kIOPMDriverAssertionLevelOff) {
5297 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5298 }
5299 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5300 kIOPMDriverAssertionLevelOff) {
5301 currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5302 }
5303 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5304 kIOPMDriverAssertionLevelOff) {
5305 currentFactors |= kIOPMSleepFactorThunderboltDevice;
5306 }
5307 if (_scheduledAlarmMask != 0) {
5308 currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5309 }
5310 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5311 kIOPMDriverAssertionLevelOff) {
5312 currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5313 }
5314 #define TCPKEEPALIVE 1
5315 #if TCPKEEPALIVE
5316 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5317 kIOPMDriverAssertionLevelOff) {
5318 currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5319 }
5320 #endif
5321 if (!powerOffEnabled) {
5322 currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5323 }
5324 if (desktopMode) {
5325 currentFactors |= kIOPMSleepFactorExternalDisplay;
5326 }
5327 if (userWasActive) {
5328 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5329 }
5330 if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5331 currentFactors |= kIOPMSleepFactorHibernateFailed;
5332 }
5333 if (thermalWarningState) {
5334 currentFactors |= kIOPMSleepFactorThermalWarning;
5335 }
5336
5337 for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) {
5338 uint32_t factor = 1 << factorBit;
5339 if (factor & currentFactors) {
5340 strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf));
5341 strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf));
5342 }
5343 }
5344 DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5345
5346 if (gSleepPolicyHandler) {
5347 uint32_t savedHibernateMode;
5348 IOReturn result;
5349
5350 if (!gSleepPolicyVars) {
5351 gSleepPolicyVars = IOMallocType(IOPMSystemSleepPolicyVariables);
5352 }
5353 gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
5354 gSleepPolicyVars->version = kIOPMSystemSleepPolicyVersion;
5355 gSleepPolicyVars->currentCapability = _currentCapability;
5356 gSleepPolicyVars->highestCapability = _highestCapability;
5357 gSleepPolicyVars->sleepFactors = currentFactors;
5358 gSleepPolicyVars->sleepReason = lastSleepReason;
5359 gSleepPolicyVars->sleepPhase = sleepPhase;
5360 gSleepPolicyVars->standbyDelay = standbyDelay;
5361 gSleepPolicyVars->standbyTimer = standbyTimer;
5362 gSleepPolicyVars->poweroffDelay = powerOffDelay;
5363 gSleepPolicyVars->scheduledAlarms = _scheduledAlarmMask | _userScheduledAlarmMask;
5364 gSleepPolicyVars->poweroffTimer = powerOffTimer;
5365
5366 if (kIOPMSleepPhase0 == sleepPhase) {
5367 // preserve hibernateMode
5368 savedHibernateMode = gSleepPolicyVars->hibernateMode;
5369 gSleepPolicyVars->hibernateMode = *hibMode;
5370 } else if (kIOPMSleepPhase1 == sleepPhase) {
5371 // use original hibernateMode for phase2
5372 gSleepPolicyVars->hibernateMode = *hibMode;
5373 }
5374
5375 result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5376
5377 if (kIOPMSleepPhase0 == sleepPhase) {
5378 // restore hibernateMode
5379 gSleepPolicyVars->hibernateMode = savedHibernateMode;
5380 }
5381
5382 if ((result != kIOReturnSuccess) ||
5383 (kIOPMSleepTypeInvalid == params->sleepType) ||
5384 (params->sleepType >= kIOPMSleepTypeLast) ||
5385 (kIOPMSystemSleepParametersVersion != params->version)) {
5386 MSG("sleep policy handler error\n");
5387 goto done;
5388 }
5389
5390 if ((getSleepTypeAttributes(params->sleepType) &
5391 kIOPMSleepAttributeHibernateSetup) &&
5392 ((*hibMode & kIOHibernateModeOn) == 0)) {
5393 *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5394 }
5395
5396 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5397 params->version, params->sleepType, params->sleepFlags,
5398 params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
5399 found = true;
5400 goto done;
5401 }
5402
5403 // Policy table is meaningless without standby enabled
5404 if (!standbyEnabled) {
5405 goto done;
5406 }
5407
5408 // Validate the sleep policy table
5409 policyData = OSDynamicCast(OSData, prop.get());
5410 if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5411 goto done;
5412 }
5413
5414 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5415 if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5416 (pt->version != 1) || (0 == pt->entryCount)) {
5417 goto done;
5418 }
5419
5420 if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5421 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5422 goto done;
5423 }
5424
5425 for (uint32_t i = 0; i < pt->entryCount; i++) {
5426 const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
5427 mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
5428
5429 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5430 entry->factorMask, entry->factorBits,
5431 entry->sleepFlags, entry->wakeEvents, mismatch);
5432 if (mismatch) {
5433 continue;
5434 }
5435
5436 DLOG("^ found match\n");
5437 found = true;
5438
5439 params->version = kIOPMSystemSleepParametersVersion;
5440 params->reserved1 = 1;
5441 if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5442 params->sleepType = kIOPMSleepTypeStandby;
5443 } else {
5444 params->sleepType = kIOPMSleepTypeNormalSleep;
5445 }
5446
5447 params->ecWakeEvents = entry->wakeEvents;
5448 if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5449 if (kIOPMSleepPhase2 == sleepPhase) {
5450 clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5451
5452 if (!_standbyTimerResetSeconds ||
5453 (now_secs <= _standbyTimerResetSeconds)) {
5454 // Reset standby timer adjustment
5455 _standbyTimerResetSeconds = now_secs;
5456 DLOG("standby delay %u, reset %u\n",
5457 standbyDelay, (uint32_t) _standbyTimerResetSeconds);
5458 } else if (standbyDelay) {
5459 // Shorten the standby delay timer
5460 clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
5461 if (standbyDelay > elapsed) {
5462 standbyDelay -= elapsed;
5463 } else {
5464 standbyDelay = 1; // must be > 0
5465 }
5466 DLOG("standby delay %u, elapsed %u\n",
5467 standbyDelay, (uint32_t) elapsed);
5468 }
5469 }
5470 params->ecWakeTimer = standbyDelay;
5471 } else if (kIOPMSleepPhase2 == sleepPhase) {
5472 // A sleep that does not enable the sleep timer will reset
5473 // the standby delay adjustment.
5474 _standbyTimerResetSeconds = 0;
5475 }
5476 break;
5477 }
5478
5479 done:
5480 return found;
5481 }
5482
5483 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5484
5485 void
5486 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5487 {
5488 // Evaluate early (priority interest phase), before drivers sleep.
5489
5490 DLOG("%s\n", __FUNCTION__);
5491 removeProperty(kIOPMSystemSleepParametersKey);
5492
5493 // Full wake resets the standby timer delay adjustment
5494 if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5495 _standbyTimerResetSeconds = 0;
5496 }
5497
5498 hibernateDisabled = false;
5499 hibernateMode = 0;
5500 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5501
5502 // Save for late evaluation if sleep is aborted
5503 bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5504
5505 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5506 &hibernateMode)) {
5507 if (!hibernateRetry &&
5508 ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5509 kIOPMSleepAttributeHibernateSetup) == 0)) {
5510 // skip hibernate setup
5511 hibernateDisabled = true;
5512 }
5513 }
5514
5515 // Publish IOPMSystemSleepType
5516 uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5517 if (sleepType == kIOPMSleepTypeInvalid) {
5518 // no sleep policy
5519 sleepType = kIOPMSleepTypeNormalSleep;
5520 if (hibernateMode & kIOHibernateModeOn) {
5521 sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5522 kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5523 }
5524 } else if ((sleepType == kIOPMSleepTypeStandby) &&
5525 (gEarlySystemSleepParams.ecPoweroffTimer)) {
5526 // report the lowest possible sleep state
5527 sleepType = kIOPMSleepTypePowerOff;
5528 }
5529
5530 setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5531 }
5532
5533 void
5534 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5535 {
5536 IOPMSystemSleepParameters params;
5537 OSSharedPtr<OSData> paramsData;
5538 bool wakeNow;
5539 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5540
5541 DLOG("%s\n", __FUNCTION__);
5542
5543 bzero(¶ms, sizeof(params));
5544 wakeNow = false;
5545 if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2, &hibernateMode)) {
5546 if ((kIOPMSleepTypeStandby == params.sleepType)
5547 && gIOHibernateStandbyDisabled && gSleepPolicyVars
5548 && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5549 & gSleepPolicyVars->sleepFactors))) {
5550 standbyNixed = true;
5551 wakeNow = true;
5552 }
5553 if (wakeNow
5554 || ((hibernateDisabled || hibernateAborted) &&
5555 (getSleepTypeAttributes(params.sleepType) &
5556 kIOPMSleepAttributeHibernateSetup))) {
5557 // Final evaluation picked a state requiring hibernation,
5558 // but hibernate isn't going to proceed. Arm a short sleep using
5559 // the early non-hibernate sleep parameters.
5560 bcopy(&gEarlySystemSleepParams, ¶ms, sizeof(params));
5561 params.sleepType = kIOPMSleepTypeAbortedSleep;
5562 params.ecWakeTimer = 1;
5563 if (standbyNixed) {
5564 resetTimers = true;
5565 } else {
5566 // Set hibernateRetry flag to force hibernate setup on the
5567 // next sleep.
5568 hibernateRetry = true;
5569 }
5570 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5571 params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5572 } else {
5573 hibernateRetry = false;
5574 }
5575
5576 if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5577 resetTimers = false;
5578 }
5579
5580 paramsData = OSData::withValue(params);
5581 if (paramsData) {
5582 setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5583 }
5584
5585 if (getSleepTypeAttributes(params.sleepType) &
5586 kIOPMSleepAttributeHibernateSleep) {
5587 // Disable sleep to force hibernation
5588 gIOHibernateMode &= ~kIOHibernateModeSleep;
5589 }
5590 }
5591 }
5592
5593 bool
5594 IOPMrootDomain::getHibernateSettings(
5595 uint32_t * hibernateModePtr,
5596 uint32_t * hibernateFreeRatio,
5597 uint32_t * hibernateFreeTime )
5598 {
5599 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5600 // has updated the hibernateDisabled flag.
5601
5602 bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
5603 getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
5604 getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
5605 if (hibernateDisabled) {
5606 *hibernateModePtr = 0;
5607 } else if (gSleepPolicyHandler) {
5608 *hibernateModePtr = hibernateMode;
5609 }
5610 DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5611 return ok;
5612 }
5613
5614 bool
5615 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5616 {
5617 OSSharedPtr<OSObject> optionsProp;
5618 OSDictionary * optionsDict;
5619 OSSharedPtr<OSObject> obj;
5620 OSNumber * num;
5621 bool ok = false;
5622
5623 optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5624 optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5625
5626 if (optionsDict) {
5627 obj.reset(optionsDict->getObject(key), OSRetain);
5628 }
5629 if (!obj) {
5630 obj = copyProperty(key);
5631 }
5632 if (obj) {
5633 if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5634 *option = num->unsigned32BitValue();
5635 ok = true;
5636 } else if (OSDynamicCast(OSBoolean, obj.get())) {
5637 *option = (obj == kOSBooleanTrue) ? 1 : 0;
5638 ok = true;
5639 }
5640 }
5641
5642 return ok;
5643 }
5644 #endif /* HIBERNATION */
5645
5646 IOReturn
5647 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5648 {
5649 #if HIBERNATION
5650 IOPMSystemSleepParameters params;
5651 uint32_t hibMode = 0;
5652 bool ok;
5653
5654 if (gIOPMWorkLoop->inGate() == false) {
5655 IOReturn ret = gIOPMWorkLoop->runAction(
5656 OSMemberFunctionCast(IOWorkLoop::Action, this,
5657 &IOPMrootDomain::getSystemSleepType),
5658 (OSObject *) this,
5659 (void *) sleepType, (void *) standbyTimer);
5660 return ret;
5661 }
5662
5663 getSleepOption(kIOHibernateModeKey, &hibMode);
5664 bzero(¶ms, sizeof(params));
5665
5666 ok = evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase0, &hibMode);
5667 if (ok) {
5668 *sleepType = params.sleepType;
5669 if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5670 !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5671 DLOG("Standby delay is not set\n");
5672 *standbyTimer = 0;
5673 }
5674 return kIOReturnSuccess;
5675 }
5676 #endif
5677
5678 return kIOReturnUnsupported;
5679 }
5680
5681 // MARK: -
5682 // MARK: Shutdown and Restart
5683
5684 //******************************************************************************
5685 // handlePlatformHaltRestart
5686 //
5687 //******************************************************************************
5688
5689 // Phases while performing shutdown/restart
5690 typedef enum {
5691 kNotifyDone = 0x00,
5692 kNotifyPriorityClients = 0x10,
5693 kNotifyPowerPlaneDrivers = 0x20,
5694 kNotifyHaltRestartAction = 0x30,
5695 kQuiescePM = 0x40,
5696 } shutdownPhase_t;
5697
5698
5699 struct HaltRestartApplierContext {
5700 IOPMrootDomain * RootDomain;
5701 unsigned long PowerState;
5702 IOPMPowerFlags PowerFlags;
5703 UInt32 MessageType;
5704 UInt32 Counter;
5705 const char * LogString;
5706 shutdownPhase_t phase;
5707
5708 IOServiceInterestHandler handler;
5709 } gHaltRestartCtx;
5710
5711 const char *
5712 shutdownPhase2String(shutdownPhase_t phase)
5713 {
5714 switch (phase) {
5715 case kNotifyDone:
5716 return "Notifications completed";
5717 case kNotifyPriorityClients:
5718 return "Notifying priority clients";
5719 case kNotifyPowerPlaneDrivers:
5720 return "Notifying power plane drivers";
5721 case kNotifyHaltRestartAction:
5722 return "Notifying HaltRestart action handlers";
5723 case kQuiescePM:
5724 return "Quiescing PM";
5725 default:
5726 return "Unknown";
5727 }
5728 }
5729
5730 static void
5731 platformHaltRestartApplier( OSObject * object, void * context )
5732 {
5733 IOPowerStateChangeNotification notify;
5734 HaltRestartApplierContext * ctx;
5735 AbsoluteTime startTime, elapsedTime;
5736 uint32_t deltaTime;
5737
5738 ctx = (HaltRestartApplierContext *) context;
5739
5740 _IOServiceInterestNotifier * notifier;
5741 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5742 memset(¬ify, 0, sizeof(notify));
5743 notify.powerRef = (void *)(uintptr_t)ctx->Counter;
5744 notify.returnValue = 0;
5745 notify.stateNumber = ctx->PowerState;
5746 notify.stateFlags = ctx->PowerFlags;
5747
5748 if (notifier) {
5749 ctx->handler = notifier->handler;
5750 }
5751
5752 clock_get_uptime(&startTime);
5753 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)¬ify );
5754 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5755
5756 if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
5757 LOG("%s handler %p took %u ms\n",
5758 ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
5759 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
5760 }
5761
5762 ctx->handler = NULL;
5763 ctx->Counter++;
5764 }
5765
5766 static void
5767 quiescePowerTreeCallback( void * target, void * param )
5768 {
5769 IOLockLock(gPMHaltLock);
5770 gPMQuiesced = true;
5771 thread_wakeup(param);
5772 IOLockUnlock(gPMHaltLock);
5773 }
5774
5775 void
5776 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5777 {
5778 AbsoluteTime startTime, elapsedTime;
5779 uint32_t deltaTime;
5780 bool nvramSync = false;
5781
5782 memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5783 gHaltRestartCtx.RootDomain = this;
5784
5785 clock_get_uptime(&startTime);
5786 switch (pe_type) {
5787 case kPEHaltCPU:
5788 case kPEUPSDelayHaltCPU:
5789 gHaltRestartCtx.PowerState = OFF_STATE;
5790 gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5791 gHaltRestartCtx.LogString = "PowerOff";
5792 nvramSync = true;
5793 break;
5794
5795 case kPERestartCPU:
5796 gHaltRestartCtx.PowerState = RESTART_STATE;
5797 gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5798 gHaltRestartCtx.LogString = "Restart";
5799 nvramSync = true;
5800 break;
5801
5802 case kPEPagingOff:
5803 gHaltRestartCtx.PowerState = ON_STATE;
5804 gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5805 gHaltRestartCtx.LogString = "PagingOff";
5806 IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5807 #if HIBERNATION
5808 IOHibernateSystemRestart();
5809 #endif
5810 break;
5811
5812 default:
5813 return;
5814 }
5815
5816 if (nvramSync) {
5817 PESyncNVRAM();
5818 }
5819
5820 gHaltRestartCtx.phase = kNotifyPriorityClients;
5821 // Notify legacy clients
5822 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5823
5824 // For normal shutdown, turn off File Server Mode.
5825 if (kPEHaltCPU == pe_type) {
5826 OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
5827 OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32);
5828 if (setting && num) {
5829 setPMSetting(setting.get(), num.get());
5830 }
5831 }
5832
5833 if (kPEPagingOff != pe_type) {
5834 gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5835 // Notify in power tree order
5836 notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5837 }
5838
5839 gHaltRestartCtx.phase = kNotifyHaltRestartAction;
5840 #if defined(XNU_TARGET_OS_OSX)
5841 IOCPURunPlatformHaltRestartActions(pe_type);
5842 #else /* !defined(XNU_TARGET_OS_OSX) */
5843 if (kPEPagingOff != pe_type) {
5844 IOCPURunPlatformHaltRestartActions(pe_type);
5845 }
5846 #endif /* !defined(XNU_TARGET_OS_OSX) */
5847
5848 // Wait for PM to quiesce
5849 if ((kPEPagingOff != pe_type) && gPMHaltLock) {
5850 gHaltRestartCtx.phase = kQuiescePM;
5851 AbsoluteTime quiesceTime = mach_absolute_time();
5852
5853 IOLockLock(gPMHaltLock);
5854 gPMQuiesced = false;
5855 if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
5856 kIOReturnSuccess) {
5857 while (!gPMQuiesced) {
5858 IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
5859 }
5860 }
5861 IOLockUnlock(gPMHaltLock);
5862 deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
5863 DLOG("PM quiesce took %u ms\n", deltaTime);
5864 halt_log_enter("Quiesce", NULL, elapsedTime);
5865 }
5866 gHaltRestartCtx.phase = kNotifyDone;
5867
5868 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5869 LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5870
5871 halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
5872
5873 deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5874 LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5875
5876 if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
5877 printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
5878 }
5879
5880 checkShutdownTimeout();
5881 }
5882
5883 bool
5884 IOPMrootDomain::checkShutdownTimeout()
5885 {
5886 AbsoluteTime elapsedTime;
5887 uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5888
5889 if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
5890 return true;
5891 }
5892 return false;
5893 }
5894
5895 void
5896 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
5897 {
5898 if (gHaltLog) {
5899 if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
5900 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
5901 }
5902 panic("%s timed out in phase '%s'. Total %d ms:%s",
5903 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
5904 } else {
5905 panic("%s timed out in phase \'%s\'. Total %d ms",
5906 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
5907 }
5908 }
5909
5910 //******************************************************************************
5911 // shutdownSystem
5912 //
5913 //******************************************************************************
5914
5915 IOReturn
5916 IOPMrootDomain::shutdownSystem( void )
5917 {
5918 return kIOReturnUnsupported;
5919 }
5920
5921 //******************************************************************************
5922 // restartSystem
5923 //
5924 //******************************************************************************
5925
5926 IOReturn
5927 IOPMrootDomain::restartSystem( void )
5928 {
5929 return kIOReturnUnsupported;
5930 }
5931
5932 // MARK: -
5933 // MARK: System Capability
5934
5935 //******************************************************************************
5936 // tagPowerPlaneService
5937 //
5938 // Running on PM work loop thread.
5939 //******************************************************************************
5940
5941 void
5942 IOPMrootDomain::tagPowerPlaneService(
5943 IOService * service,
5944 IOPMActions * actions,
5945 IOPMPowerStateIndex maxPowerState )
5946 {
5947 uint32_t flags = 0;
5948
5949 memset(actions, 0, sizeof(*actions));
5950 actions->target = this;
5951
5952 if (service == this) {
5953 actions->actionPowerChangeStart =
5954 OSMemberFunctionCast(
5955 IOPMActionPowerChangeStart, this,
5956 &IOPMrootDomain::handleOurPowerChangeStart);
5957
5958 actions->actionPowerChangeDone =
5959 OSMemberFunctionCast(
5960 IOPMActionPowerChangeDone, this,
5961 &IOPMrootDomain::handleOurPowerChangeDone);
5962
5963 actions->actionPowerChangeOverride =
5964 OSMemberFunctionCast(
5965 IOPMActionPowerChangeOverride, this,
5966 &IOPMrootDomain::overrideOurPowerChange);
5967 return;
5968 }
5969
5970 #if DISPLAY_WRANGLER_PRESENT
5971 if (NULL != service->metaCast("IODisplayWrangler")) {
5972 // XXX should this really retain?
5973 wrangler.reset(service, OSRetain);
5974 wrangler->registerInterest(gIOGeneralInterest,
5975 &displayWranglerNotification, this, NULL);
5976
5977 // found the display wrangler, check for any display assertions already created
5978 if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
5979 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5980 wrangler->setIgnoreIdleTimer( true );
5981 }
5982 flags |= kPMActionsFlagIsDisplayWrangler;
5983 }
5984 #endif /* DISPLAY_WRANGLER_PRESENT */
5985
5986 if (service->propertyExists("IOPMStrictTreeOrder")) {
5987 flags |= kPMActionsFlagIsGraphicsDriver;
5988 }
5989 if (service->propertyExists("IOPMUnattendedWakePowerState")) {
5990 flags |= kPMActionsFlagIsAudioDriver;
5991 }
5992
5993 // Find the power connection object that is a child of the PCI host
5994 // bridge, and has a graphics/audio device attached below. Mark the
5995 // power branch for delayed child notifications.
5996
5997 if (flags) {
5998 IORegistryEntry * child = service;
5999 IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
6000
6001 while (child != this) {
6002 if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) {
6003 // Skip delaying notifications and clamping power on external graphics and audio devices.
6004 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
6005 flags = 0;
6006 break;
6007 }
6008 if ((parent == pciHostBridgeDriver) ||
6009 (parent == this)) {
6010 if (OSDynamicCast(IOPowerConnection, child)) {
6011 IOPowerConnection * conn = (IOPowerConnection *) child;
6012 conn->delayChildNotification = true;
6013 DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
6014 }
6015 break;
6016 }
6017 child = parent;
6018 parent = child->getParentEntry(gIOPowerPlane);
6019 }
6020 }
6021
6022 OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
6023 if (prop) {
6024 OSNumber * num = OSDynamicCast(OSNumber, prop.get());
6025 if (num) {
6026 actions->darkWakePowerState = num->unsigned32BitValue();
6027 if (actions->darkWakePowerState < maxPowerState) {
6028 flags |= kPMActionsFlagHasDarkWakePowerState;
6029 }
6030 }
6031 }
6032
6033
6034 if (flags) {
6035 DLOG("%s tag flags %x\n", service->getName(), flags);
6036 actions->flags |= flags;
6037 actions->actionPowerChangeOverride =
6038 OSMemberFunctionCast(
6039 IOPMActionPowerChangeOverride, this,
6040 &IOPMrootDomain::overridePowerChangeForService);
6041
6042 if (flags & kPMActionsFlagIsDisplayWrangler) {
6043 actions->actionActivityTickle =
6044 OSMemberFunctionCast(
6045 IOPMActionActivityTickle, this,
6046 &IOPMrootDomain::handleActivityTickleForDisplayWrangler);
6047
6048 actions->actionUpdatePowerClient =
6049 OSMemberFunctionCast(
6050 IOPMActionUpdatePowerClient, this,
6051 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
6052 }
6053 return;
6054 }
6055
6056 // Locate the first PCI host bridge for PMTrace.
6057 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
6058 IOService * provider = service->getProvider();
6059 if (OSDynamicCast(IOPlatformDevice, provider) &&
6060 provider->inPlane(gIODTPlane)) {
6061 pciHostBridgeDevice.reset(provider, OSNoRetain);
6062 pciHostBridgeDriver.reset(service, OSNoRetain);
6063 DLOG("PMTrace found PCI host bridge %s->%s\n",
6064 provider->getName(), service->getName());
6065 }
6066 }
6067
6068 // Tag top-level PCI devices. The order of PMinit() call does not
6069 // change across boots and is used as the PCI bit number.
6070 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
6071 // Would prefer to check built-in property, but tagPowerPlaneService()
6072 // is called before pciDevice->registerService().
6073 IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
6074 if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) {
6075 int bit = pmTracer->recordTopLevelPCIDevice( service );
6076 if (bit >= 0) {
6077 // Save the assigned bit for fast lookup.
6078 actions->flags |= (bit & kPMActionsPCIBitNumberMask);
6079
6080 actions->actionPowerChangeStart =
6081 OSMemberFunctionCast(
6082 IOPMActionPowerChangeStart, this,
6083 &IOPMrootDomain::handlePowerChangeStartForPCIDevice);
6084
6085 actions->actionPowerChangeDone =
6086 OSMemberFunctionCast(
6087 IOPMActionPowerChangeDone, this,
6088 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
6089 }
6090 }
6091 }
6092 }
6093
6094 //******************************************************************************
6095 // PM actions for root domain
6096 //******************************************************************************
6097
6098 void
6099 IOPMrootDomain::overrideOurPowerChange(
6100 IOService * service,
6101 IOPMActions * actions,
6102 const IOPMRequest * request,
6103 IOPMPowerStateIndex * inOutPowerState,
6104 IOPMPowerChangeFlags * inOutChangeFlags )
6105 {
6106 uint32_t changeFlags = *inOutChangeFlags;
6107 uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
6108 uint32_t currentPowerState = (uint32_t) getPowerState();
6109
6110 if (request->getTag() == 0) {
6111 // Set a tag for any request that originates from IOServicePM
6112 (const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
6113 }
6114
6115 DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6116 getPowerStateString(currentPowerState),
6117 getPowerStateString(desiredPowerState),
6118 _currentCapability, changeFlags,
6119 request->getTag());
6120
6121
6122 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6123 /*
6124 * ASBM send lowBattery notifications every 1 second until the device
6125 * enters hibernation. This queues up multiple sleep requests.
6126 * After the device wakes from hibernation, none of these previously
6127 * queued sleep requests are valid.
6128 * lowBattteryCondition variable is set when ASBM notifies rootDomain
6129 * and is cleared at the very last point in sleep.
6130 * Any attempt to sleep with reason kIOPMSleepReasonLowPower without
6131 * lowBatteryCondition is invalid
6132 */
6133 if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) {
6134 if (!lowBatteryCondition) {
6135 DLOG("Duplicate lowBattery sleep");
6136 *inOutChangeFlags |= kIOPMNotDone;
6137 return;
6138 }
6139 }
6140 #endif
6141
6142 if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
6143 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6144 *inOutChangeFlags |= kIOPMNotDone;
6145 return;
6146 }
6147
6148 if (changeFlags & kIOPMParentInitiated) {
6149 // Root parent is permanently pegged at max power,
6150 // a parent initiated power change is unexpected.
6151 *inOutChangeFlags |= kIOPMNotDone;
6152 return;
6153 }
6154
6155 #if HIBERNATION && defined(__arm64__)
6156 if (lowBatteryCondition && (desiredPowerState < currentPowerState)) {
6157 if (!ml_is_secure_hib_supported()) {
6158 // If hibernation is unsupported, reject sleep requests to avoid
6159 // racing with system shutdown.
6160 *inOutChangeFlags |= kIOPMNotDone;
6161 return;
6162 }
6163 }
6164 #endif /* HIBERNATION && defined(__arm64__) */
6165
6166 if (desiredPowerState < currentPowerState) {
6167 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6168 // Root domain is dropping power state from ON->SLEEP.
6169 // If system is in full wake, first enter dark wake by
6170 // converting the power drop to a capability change.
6171 // Once in dark wake, transition to sleep state ASAP.
6172
6173 darkWakeToSleepASAP = true;
6174
6175 // Drop graphics and audio capability
6176 _desiredCapability &= ~(
6177 kIOPMSystemCapabilityGraphics |
6178 kIOPMSystemCapabilityAudio);
6179
6180 // Convert to capability change (ON->ON)
6181 *inOutPowerState = getRUN_STATE();
6182 *inOutChangeFlags |= kIOPMSynchronize;
6183
6184 // Revert device desire from SLEEP to ON
6185 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6186 } else {
6187 // System is already in dark wake, ok to drop power state.
6188 // Broadcast root power down to entire tree.
6189 *inOutChangeFlags |= kIOPMRootChangeDown;
6190 }
6191 } else if (desiredPowerState > currentPowerState) {
6192 if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
6193 // Broadcast power up when waking from sleep, but not for the
6194 // initial power change at boot by checking for cpu capability.
6195 *inOutChangeFlags |= kIOPMRootChangeUp;
6196 }
6197 }
6198 }
6199
6200 void
6201 IOPMrootDomain::handleOurPowerChangeStart(
6202 IOService * service,
6203 IOPMActions * actions,
6204 const IOPMRequest * request,
6205 IOPMPowerStateIndex newPowerState,
6206 IOPMPowerChangeFlags * inOutChangeFlags )
6207 {
6208 IOPMRequestTag requestTag = request->getTag();
6209 IOPMRequestTag sleepReason;
6210
6211 uint32_t changeFlags = *inOutChangeFlags;
6212 uint32_t currentPowerState = (uint32_t) getPowerState();
6213 bool publishSleepReason = false;
6214
6215 // Check if request has a valid sleep reason
6216 sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6217 if (sleepReason < kIOPMSleepReasonClamshell) {
6218 sleepReason = kIOPMSleepReasonIdle;
6219 }
6220
6221 _systemTransitionType = kSystemTransitionNone;
6222 _systemMessageClientMask = 0;
6223 capabilityLoss = false;
6224 toldPowerdCapWillChange = false;
6225
6226 // Emergency notifications may arrive after the initial sleep request
6227 // has been queued. Override the sleep reason so powerd and others can
6228 // treat this as an emergency sleep.
6229 if (lowBatteryCondition) {
6230 sleepReason = kIOPMSleepReasonLowPower;
6231 } else if (thermalEmergencyState) {
6232 sleepReason = kIOPMSleepReasonThermalEmergency;
6233 }
6234
6235 // 1. Explicit capability change.
6236 if (changeFlags & kIOPMSynchronize) {
6237 if (newPowerState == ON_STATE) {
6238 if (changeFlags & kIOPMSyncNoChildNotify) {
6239 _systemTransitionType = kSystemTransitionNewCapClient;
6240 } else {
6241 _systemTransitionType = kSystemTransitionCapability;
6242 }
6243 }
6244 }
6245 // 2. Going to sleep (cancellation still possible).
6246 else if (newPowerState < currentPowerState) {
6247 _systemTransitionType = kSystemTransitionSleep;
6248 }
6249 // 3. Woke from (idle or demand) sleep.
6250 else if (!systemBooting &&
6251 (changeFlags & kIOPMSelfInitiated) &&
6252 (newPowerState > currentPowerState)) {
6253 _systemTransitionType = kSystemTransitionWake;
6254 _desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
6255
6256 // Early exit from dark wake to full (e.g. LID open)
6257 if (kFullWakeReasonNone != fullWakeReason) {
6258 _desiredCapability |= (
6259 kIOPMSystemCapabilityGraphics |
6260 kIOPMSystemCapabilityAudio);
6261
6262 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6263 if (fullWakeReason == kFullWakeReasonLocalUser) {
6264 darkWakeExit = true;
6265 darkWakeToSleepASAP = false;
6266 setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ?
6267 kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser);
6268 }
6269 #endif
6270 }
6271 #if HIBERNATION
6272 IOHibernateSetWakeCapabilities(_desiredCapability);
6273 #endif
6274 }
6275
6276 // Update pending wake capability at the beginning of every
6277 // state transition (including synchronize). This will become
6278 // the current capability at the end of the transition.
6279
6280 if (kSystemTransitionSleep == _systemTransitionType) {
6281 _pendingCapability = 0;
6282 capabilityLoss = true;
6283 } else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6284 _pendingCapability = _desiredCapability |
6285 kIOPMSystemCapabilityCPU |
6286 kIOPMSystemCapabilityNetwork;
6287
6288 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6289 _pendingCapability |= kIOPMSystemCapabilityAudio;
6290 }
6291
6292 if ((kSystemTransitionCapability == _systemTransitionType) &&
6293 (_pendingCapability == _currentCapability)) {
6294 // Cancel the PM state change.
6295 _systemTransitionType = kSystemTransitionNone;
6296 *inOutChangeFlags |= kIOPMNotDone;
6297 }
6298 if (__builtin_popcount(_pendingCapability) <
6299 __builtin_popcount(_currentCapability)) {
6300 capabilityLoss = true;
6301 }
6302 }
6303
6304 // 1. Capability change.
6305 if (kSystemTransitionCapability == _systemTransitionType) {
6306 // Dark to Full transition.
6307 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6308 tracePoint( kIOPMTracePointDarkWakeExit );
6309
6310 #if defined(XNU_TARGET_OS_OSX)
6311 // rdar://problem/65627936
6312 // When a dark->full wake promotion is scheduled before an ON->SLEEP
6313 // power state drop, invalidate any request to drop power state already
6314 // in the queue, including the override variant, unless full wake cannot
6315 // be sustained. Any power state drop queued after this SustainFullWake
6316 // request will not be affected.
6317 if (checkSystemCanSustainFullWake()) {
6318 changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake);
6319 }
6320 #endif
6321
6322 willEnterFullWake();
6323 }
6324
6325 // Full to Dark transition.
6326 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6327 // Clear previous stats
6328 IOLockLock(pmStatsLock);
6329 if (pmStatsAppResponses) {
6330 pmStatsAppResponses = OSArray::withCapacity(5);
6331 }
6332 IOLockUnlock(pmStatsLock);
6333
6334 tracePoint( kIOPMTracePointDarkWakeEntry );
6335 *inOutChangeFlags |= kIOPMSyncTellPowerDown;
6336 _systemMessageClientMask = kSystemMessageClientPowerd |
6337 kSystemMessageClientLegacyApp;
6338
6339 // rdar://15971327
6340 // Prevent user active transitions before notifying clients
6341 // that system will sleep.
6342 preventTransitionToUserActive(true);
6343
6344 IOService::setAdvisoryTickleEnable( false );
6345
6346 // Publish the sleep reason for full to dark wake
6347 publishSleepReason = true;
6348 lastSleepReason = fullToDarkReason = sleepReason;
6349
6350 // Publish a UUID for the Sleep --> Wake cycle
6351 handlePublishSleepWakeUUID(true);
6352 if (sleepDelaysReport) {
6353 clock_get_uptime(&ts_sleepStart);
6354 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
6355 }
6356
6357 darkWakeExit = false;
6358 }
6359 }
6360 // 2. System sleep.
6361 else if (kSystemTransitionSleep == _systemTransitionType) {
6362 // Beginning of a system sleep transition.
6363 // Cancellation is still possible.
6364 tracePoint( kIOPMTracePointSleepStarted );
6365
6366 _systemMessageClientMask = kSystemMessageClientAll;
6367 if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6368 _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6369 }
6370 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
6371 // Kernel priority clients are only notified on the initial
6372 // transition to full wake, so don't notify them unless system
6373 // has gained graphics capability since the last system wake.
6374 _systemMessageClientMask &= ~kSystemMessageClientKernel;
6375 } else {
6376 // System was in full wake, but the downwards power transition is driven
6377 // by a request that originates from IOServicePM, so it isn't tagged with
6378 // a valid system sleep reason.
6379 if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) {
6380 // Publish the same reason for full to dark
6381 sleepReason = fullToDarkReason;
6382 }
6383 }
6384 #if HIBERNATION
6385 gIOHibernateState = 0;
6386 #endif
6387
6388 // Record the reason for dark wake back to sleep
6389 // System may not have ever achieved full wake
6390
6391 publishSleepReason = true;
6392 lastSleepReason = sleepReason;
6393 if (sleepDelaysReport) {
6394 clock_get_uptime(&ts_sleepStart);
6395 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
6396 }
6397 }
6398 // 3. System wake.
6399 else if (kSystemTransitionWake == _systemTransitionType) {
6400 tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6401 // Clear stats about sleep
6402
6403 if (AOT_STATE == newPowerState) {
6404 _pendingCapability = 0;
6405 }
6406
6407 if (AOT_STATE == currentPowerState) {
6408 // Wake events are no longer accepted after waking to AOT_STATE.
6409 // Re-enable wake event acceptance to append wake events claimed
6410 // during the AOT to ON_STATE transition.
6411 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable);
6412 }
6413
6414 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6415 willEnterFullWake();
6416 }
6417 }
6418
6419 // The only location where the sleep reason is published. At this point
6420 // sleep can still be cancelled, but sleep reason should be published
6421 // early for logging purposes.
6422
6423 if (publishSleepReason) {
6424 static const char * IOPMSleepReasons[] =
6425 {
6426 kIOPMClamshellSleepKey,
6427 kIOPMPowerButtonSleepKey,
6428 kIOPMSoftwareSleepKey,
6429 kIOPMOSSwitchHibernationKey,
6430 kIOPMIdleSleepKey,
6431 kIOPMLowPowerSleepKey,
6432 kIOPMThermalEmergencySleepKey,
6433 kIOPMMaintenanceSleepKey,
6434 kIOPMSleepServiceExitKey,
6435 kIOPMDarkWakeThermalEmergencyKey,
6436 kIOPMNotificationWakeExitKey
6437 };
6438
6439 // Record sleep cause in IORegistry
6440 uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
6441 if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
6442 DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
6443 #if DEVELOPMENT || DEBUG
6444 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6445 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6446 "Sleep Reason", "%s\n", IOPMSleepReasons[reasonIndex]
6447 );
6448 #endif /* DEVELOPMENT || DEBUG */
6449 setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
6450 }
6451 }
6452
6453 if ((kSystemTransitionNone != _systemTransitionType) &&
6454 (kSystemTransitionNewCapClient != _systemTransitionType)) {
6455 _systemStateGeneration++;
6456 systemDarkWake = false;
6457
6458 DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6459 getPowerStateString(currentPowerState),
6460 getPowerStateString((uint32_t) newPowerState),
6461 _currentCapability, _pendingCapability,
6462 *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask,
6463 requestTag);
6464 #if DEVELOPMENT || DEBUG
6465 if (currentPowerState != (uint32_t) newPowerState) {
6466 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6467 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6468 "Start Power State Trans.",
6469 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6470 getPowerStateString(currentPowerState),
6471 getPowerStateString((uint32_t) newPowerState),
6472 _currentCapability,
6473 _pendingCapability,
6474 *inOutChangeFlags,
6475 _systemStateGeneration,
6476 _systemMessageClientMask,
6477 requestTag
6478 );
6479 }
6480 #endif /* DEVELOPMENT || DEBUG */
6481 }
6482
6483 if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6484 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6485 }
6486 if (_aotNow && (ON_STATE == newPowerState)) {
6487 WAKEEVENT_LOCK();
6488 aotShouldExit(true);
6489 WAKEEVENT_UNLOCK();
6490 aotExit(false);
6491 }
6492 }
6493
6494 void
6495 IOPMrootDomain::handleOurPowerChangeDone(
6496 IOService * service,
6497 IOPMActions * actions,
6498 const IOPMRequest * request,
6499 IOPMPowerStateIndex oldPowerState,
6500 IOPMPowerChangeFlags changeFlags )
6501 {
6502 if (kSystemTransitionNewCapClient == _systemTransitionType) {
6503 _systemTransitionType = kSystemTransitionNone;
6504 return;
6505 }
6506
6507 if (_systemTransitionType != kSystemTransitionNone) {
6508 uint32_t currentPowerState = (uint32_t) getPowerState();
6509
6510 if (changeFlags & kIOPMNotDone) {
6511 // Power down was cancelled or vetoed.
6512 _pendingCapability = _currentCapability;
6513 lastSleepReason = 0;
6514
6515 // When sleep is cancelled or reverted, don't report
6516 // the target (lower) power state as the previous state.
6517 oldPowerState = currentPowerState;
6518
6519 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
6520 CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
6521 #if defined(XNU_TARGET_OS_OSX)
6522 pmPowerStateQueue->submitPowerEvent(
6523 kPowerEventPolicyStimulus,
6524 (void *) kStimulusDarkWakeReentry,
6525 _systemStateGeneration );
6526 #else /* !defined(XNU_TARGET_OS_OSX) */
6527 // On embedded, there are no factors that can prolong a
6528 // "darkWake" when a power down is vetoed. We need to
6529 // promote to "fullWake" at least once so that factors
6530 // that prevent idle sleep can assert themselves if required
6531 pmPowerStateQueue->submitPowerEvent(
6532 kPowerEventPolicyStimulus,
6533 (void *) kStimulusDarkWakeActivityTickle);
6534 #endif /* !defined(XNU_TARGET_OS_OSX) */
6535 }
6536
6537 // Revert device desire to max.
6538 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6539 } else {
6540 // Send message on dark wake to full wake promotion.
6541 // tellChangeUp() handles the normal SLEEP->ON case.
6542
6543 if (kSystemTransitionCapability == _systemTransitionType) {
6544 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6545 lastSleepReason = 0; // stop logging wrangler tickles
6546 tellClients(kIOMessageSystemHasPoweredOn);
6547 }
6548 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6549 // Going dark, reset full wake state
6550 // userIsActive will be cleared by wrangler powering down
6551 fullWakeReason = kFullWakeReasonNone;
6552
6553 if (ts_sleepStart) {
6554 clock_get_uptime(&wake2DarkwakeDelay);
6555 SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
6556 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
6557 ts_sleepStart = 0;
6558 }
6559 }
6560 }
6561
6562 // Reset state after exiting from dark wake.
6563
6564 if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6565 CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6566 darkWakeMaintenance = false;
6567 darkWakeToSleepASAP = false;
6568 pciCantSleepValid = false;
6569 darkWakeSleepService = false;
6570
6571 if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6572 // Remove the influence of display power assertion
6573 // before next system wake.
6574 if (wrangler) {
6575 wrangler->changePowerStateForRootDomain(
6576 kWranglerPowerStateMin );
6577 }
6578 removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6579 }
6580 }
6581
6582 // Entered dark mode.
6583
6584 if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6585 (_pendingCapability & kIOPMSystemCapabilityCPU)) {
6586 // Queue an evaluation of whether to remain in dark wake,
6587 // and for how long. This serves the purpose of draining
6588 // any assertions from the queue.
6589
6590 pmPowerStateQueue->submitPowerEvent(
6591 kPowerEventPolicyStimulus,
6592 (void *) kStimulusDarkWakeEntry,
6593 _systemStateGeneration );
6594 }
6595 }
6596
6597 #if DEVELOPMENT || DEBUG
6598 if (currentPowerState != (uint32_t) oldPowerState) {
6599 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6600 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6601 "Finish Power State Trans.",
6602 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6603 getPowerStateString((uint32_t)oldPowerState),
6604 getPowerStateString(currentPowerState),
6605 _currentCapability,
6606 _pendingCapability,
6607 changeFlags,
6608 _systemStateGeneration,
6609 _systemMessageClientMask,
6610 request->getTag()
6611 );
6612 }
6613 #endif /* DEVELOPMENT || DEBUG */
6614
6615 DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6616 getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState),
6617 _currentCapability, _pendingCapability,
6618 changeFlags, _systemStateGeneration, _systemMessageClientMask,
6619 request->getTag());
6620
6621 if ((currentPowerState == ON_STATE) && pmAssertions) {
6622 pmAssertions->reportCPUBitAccounting();
6623 }
6624
6625 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6626 displayWakeCnt++;
6627 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6628 if (clamshellExists && fullWakeThreadCall) {
6629 AbsoluteTime deadline;
6630 clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline);
6631 thread_call_enter_delayed(fullWakeThreadCall, deadline);
6632 }
6633 #endif
6634 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6635 darkWakeCnt++;
6636 }
6637
6638 // Update current system capability.
6639 if (_currentCapability != _pendingCapability) {
6640 _currentCapability = _pendingCapability;
6641 }
6642
6643 // Update highest system capability.
6644
6645 _highestCapability |= _currentCapability;
6646
6647 if (darkWakePostTickle &&
6648 (kSystemTransitionWake == _systemTransitionType) &&
6649 (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6650 kDarkWakeFlagPromotionLate) {
6651 darkWakePostTickle = false;
6652 reportUserInput();
6653 } else if (darkWakeExit) {
6654 requestFullWake( kFullWakeReasonLocalUser );
6655 }
6656
6657 // Reset tracepoint at completion of capability change,
6658 // completion of wake transition, and aborted sleep transition.
6659
6660 if ((_systemTransitionType == kSystemTransitionCapability) ||
6661 (_systemTransitionType == kSystemTransitionWake) ||
6662 ((_systemTransitionType == kSystemTransitionSleep) &&
6663 (changeFlags & kIOPMNotDone))) {
6664 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6665 tracePoint( kIOPMTracePointSystemUp );
6666 }
6667
6668 _systemTransitionType = kSystemTransitionNone;
6669 _systemMessageClientMask = 0;
6670 toldPowerdCapWillChange = false;
6671
6672 darkWakeLogClamp = false;
6673
6674 if (lowBatteryCondition) {
6675 privateSleepSystem(kIOPMSleepReasonLowPower);
6676 } else if (thermalEmergencyState) {
6677 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6678 } else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) {
6679 // Request for full wake is removed while system is waking up to full wake
6680 DLOG("DisplayOn fullwake request is removed\n");
6681 handleSetDisplayPowerOn(false);
6682 }
6683
6684 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6685 pmPowerStateQueue->submitPowerEvent(
6686 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6687 }
6688 }
6689 }
6690
6691 //******************************************************************************
6692 // PM actions for graphics and audio.
6693 //******************************************************************************
6694
6695 void
6696 IOPMrootDomain::overridePowerChangeForService(
6697 IOService * service,
6698 IOPMActions * actions,
6699 const IOPMRequest * request,
6700 IOPMPowerStateIndex * inOutPowerState,
6701 IOPMPowerChangeFlags * inOutChangeFlags )
6702 {
6703 uint32_t powerState = (uint32_t) *inOutPowerState;
6704 uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6705 const uint32_t actionFlags = actions->flags;
6706
6707 if (kSystemTransitionNone == _systemTransitionType) {
6708 // Not in midst of a system transition.
6709 // Do not set kPMActionsStatePowerClamped.
6710 } else if ((actions->state & kPMActionsStatePowerClamped) == 0) {
6711 bool enableClamp = false;
6712
6713 // For most drivers, enable the clamp during ON->Dark transition
6714 // which has the kIOPMSynchronize flag set in changeFlags.
6715 if ((actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6716 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6717 (changeFlags & kIOPMSynchronize)) {
6718 enableClamp = true;
6719 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6720 ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6721 ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6722 (changeFlags & kIOPMSynchronize)) {
6723 enableClamp = true;
6724 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6725 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6726 (changeFlags & kIOPMSynchronize)) {
6727 enableClamp = true;
6728 } else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) &&
6729 (_systemTransitionType == kSystemTransitionSleep)) {
6730 // For graphics drivers, clamp power when entering
6731 // system sleep. Not when dropping to dark wake.
6732 enableClamp = true;
6733 }
6734
6735 if (enableClamp) {
6736 actions->state |= kPMActionsStatePowerClamped;
6737 DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6738 service->getName(), service->getRegistryEntryID(),
6739 _pendingCapability, powerState, changeFlags);
6740 }
6741 } else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6742 bool disableClamp = false;
6743
6744 if ((actionFlags & (
6745 kPMActionsFlagIsDisplayWrangler |
6746 kPMActionsFlagIsGraphicsDriver)) &&
6747 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6748 disableClamp = true;
6749 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6750 (_pendingCapability & kIOPMSystemCapabilityAudio)) {
6751 disableClamp = true;
6752 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6753 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6754 disableClamp = true;
6755 }
6756
6757 if (disableClamp) {
6758 actions->state &= ~kPMActionsStatePowerClamped;
6759 DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6760 service->getName(), service->getRegistryEntryID(),
6761 _pendingCapability, powerState, changeFlags);
6762 }
6763 }
6764
6765 if (actions->state & kPMActionsStatePowerClamped) {
6766 uint32_t maxPowerState = 0;
6767
6768 // Determine the max power state allowed when clamp is enabled
6769 if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
6770 // Parent intiated power state changes
6771 if ((service->getPowerState() > maxPowerState) &&
6772 (actionFlags & kPMActionsFlagIsDisplayWrangler)) {
6773 maxPowerState++;
6774
6775 // Remove lingering effects of any tickle before entering
6776 // dark wake. It will take a new tickle to return to full
6777 // wake, so the existing tickle state is useless.
6778
6779 if (changeFlags & kIOPMDomainDidChange) {
6780 *inOutChangeFlags |= kIOPMExpireIdleTimer;
6781 }
6782 } else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6783 maxPowerState++;
6784 } else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6785 maxPowerState = actions->darkWakePowerState;
6786 }
6787 } else {
6788 // Deny all self-initiated changes when power is limited.
6789 // Wrangler tickle should never defeat the limiter.
6790 maxPowerState = service->getPowerState();
6791 }
6792
6793 if (powerState > maxPowerState) {
6794 DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6795 service->getName(), service->getRegistryEntryID(),
6796 powerState, maxPowerState, changeFlags);
6797 *inOutPowerState = maxPowerState;
6798
6799 if (darkWakePostTickle &&
6800 (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6801 (changeFlags & kIOPMDomainWillChange) &&
6802 ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6803 kDarkWakeFlagPromotionEarly)) {
6804 darkWakePostTickle = false;
6805 reportUserInput();
6806 }
6807 }
6808
6809 if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
6810 if (darkWakeLogClamp) {
6811 AbsoluteTime now;
6812 uint64_t nsec;
6813
6814 clock_get_uptime(&now);
6815 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
6816 absolutetime_to_nanoseconds(now, &nsec);
6817 DLOG("dark wake power clamped after %u ms\n",
6818 ((int)((nsec) / NSEC_PER_MSEC)));
6819 }
6820 darkWakePowerClamped = true;
6821 }
6822 }
6823 }
6824
6825 void
6826 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6827 IOService * service,
6828 IOPMActions * actions )
6829 {
6830 #if DISPLAY_WRANGLER_PRESENT
6831 // Warning: Not running in PM work loop context - don't modify state !!!
6832 // Trap tickle directed to IODisplayWrangler while running with graphics
6833 // capability suppressed.
6834
6835 assert(service == wrangler);
6836
6837 clock_get_uptime(&userActivityTime);
6838 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
6839 || (lastSleepReason == kIOPMSleepReasonMaintenance)
6840 || (lastSleepReason == kIOPMSleepReasonSoftware));
6841 if (aborting) {
6842 userActivityCount++;
6843 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6844 userActivityCount, lastSleepReason);
6845 }
6846
6847 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
6848 DLOG("display wrangler tickled\n");
6849 if (kIOLogPMRootDomain & gIOKitDebug) {
6850 OSReportWithBacktrace("Dark wake display tickle");
6851 }
6852 if (pmPowerStateQueue) {
6853 pmPowerStateQueue->submitPowerEvent(
6854 kPowerEventPolicyStimulus,
6855 (void *) kStimulusDarkWakeActivityTickle,
6856 true /* set wake type */ );
6857 }
6858 }
6859 #endif /* DISPLAY_WRANGLER_PRESENT */
6860 }
6861
6862 void
6863 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6864 IOService * service,
6865 IOPMActions * actions,
6866 const OSSymbol * powerClient,
6867 IOPMPowerStateIndex oldPowerState,
6868 IOPMPowerStateIndex newPowerState )
6869 {
6870 #if DISPLAY_WRANGLER_PRESENT
6871 assert(service == wrangler);
6872
6873 // This function implements half of the user active detection
6874 // by monitoring changes to the display wrangler's device desire.
6875 //
6876 // User becomes active when either:
6877 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6878 // in max power state. This desire change in absence of a power state
6879 // change is detected within. This handles the case when user becomes
6880 // active while the display is already lit by setDisplayPowerOn().
6881 //
6882 // 2. Power state change to max, and DeviceDesire is also at max.
6883 // Handled by displayWranglerNotification().
6884 //
6885 // User becomes inactive when DeviceDesire drops to sleep state or below.
6886
6887 DLOG("wrangler %s (ps %u, %u->%u)\n",
6888 powerClient->getCStringNoCopy(),
6889 (uint32_t) service->getPowerState(),
6890 (uint32_t) oldPowerState, (uint32_t) newPowerState);
6891
6892 if (powerClient == gIOPMPowerClientDevice) {
6893 if ((newPowerState > oldPowerState) &&
6894 (newPowerState == kWranglerPowerStateMax) &&
6895 (service->getPowerState() == kWranglerPowerStateMax)) {
6896 evaluatePolicy( kStimulusEnterUserActiveState );
6897 } else if ((newPowerState < oldPowerState) &&
6898 (newPowerState <= kWranglerPowerStateSleep)) {
6899 evaluatePolicy( kStimulusLeaveUserActiveState );
6900 }
6901 }
6902
6903 if (newPowerState <= kWranglerPowerStateSleep) {
6904 evaluatePolicy( kStimulusDisplayWranglerSleep );
6905 } else if (newPowerState == kWranglerPowerStateMax) {
6906 evaluatePolicy( kStimulusDisplayWranglerWake );
6907 }
6908 #endif /* DISPLAY_WRANGLER_PRESENT */
6909 }
6910
6911 //******************************************************************************
6912 // User active state management
6913 //******************************************************************************
6914
6915 void
6916 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
6917 {
6918 #if DISPLAY_WRANGLER_PRESENT
6919 _preventUserActive = prevent;
6920 if (wrangler && !_preventUserActive) {
6921 // Allowing transition to user active, but the wrangler may have
6922 // already powered ON in case of sleep cancel/revert. Poll the
6923 // same conditions checked for in displayWranglerNotification()
6924 // to bring the user active state up to date.
6925
6926 if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
6927 (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
6928 kWranglerPowerStateMax)) {
6929 evaluatePolicy( kStimulusEnterUserActiveState );
6930 }
6931 }
6932 #endif /* DISPLAY_WRANGLER_PRESENT */
6933 }
6934
6935 //******************************************************************************
6936 // Approve usage of delayed child notification by PM.
6937 //******************************************************************************
6938
6939 bool
6940 IOPMrootDomain::shouldDelayChildNotification(
6941 IOService * service )
6942 {
6943 if ((kFullWakeReasonNone == fullWakeReason) &&
6944 (kSystemTransitionWake == _systemTransitionType)) {
6945 DLOG("%s: delay child notify\n", service->getName());
6946 return true;
6947 }
6948 return false;
6949 }
6950
6951 //******************************************************************************
6952 // PM actions for PCI device.
6953 //******************************************************************************
6954
6955 void
6956 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6957 IOService * service,
6958 IOPMActions * actions,
6959 const IOPMRequest * request,
6960 IOPMPowerStateIndex powerState,
6961 IOPMPowerChangeFlags * inOutChangeFlags )
6962 {
6963 pmTracer->tracePCIPowerChange(
6964 PMTraceWorker::kPowerChangeStart,
6965 service, *inOutChangeFlags,
6966 (actions->flags & kPMActionsPCIBitNumberMask));
6967 }
6968
6969 void
6970 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6971 IOService * service,
6972 IOPMActions * actions,
6973 const IOPMRequest * request,
6974 IOPMPowerStateIndex powerState,
6975 IOPMPowerChangeFlags changeFlags )
6976 {
6977 pmTracer->tracePCIPowerChange(
6978 PMTraceWorker::kPowerChangeCompleted,
6979 service, changeFlags,
6980 (actions->flags & kPMActionsPCIBitNumberMask));
6981 }
6982
6983 //******************************************************************************
6984 // registerInterest
6985 //
6986 // Override IOService::registerInterest() for root domain clients.
6987 //******************************************************************************
6988
6989 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
6990 {
6991 friend class IOPMrootDomain;
6992 OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
6993
6994 protected:
6995 uint32_t ackTimeoutCnt;
6996 uint32_t msgType; // Last type seen by the message filter
6997 uint32_t lastSleepWakeMsgType;
6998 uint32_t msgIndex;
6999 uint32_t maxMsgDelayMS;
7000 uint32_t maxAckDelayMS;
7001 uint64_t msgAbsTime;
7002 uint64_t uuid0;
7003 uint64_t uuid1;
7004 OSSharedPtr<const OSSymbol> identifier;
7005 OSSharedPtr<const OSSymbol> clientName;
7006 };
7007
7008 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
7009
7010 OSSharedPtr<IONotifier>
7011 IOPMrootDomain::registerInterest(
7012 const OSSymbol * typeOfInterest,
7013 IOServiceInterestHandler handler,
7014 void * target, void * ref )
7015 {
7016 IOPMServiceInterestNotifier* notifier;
7017 bool isSystemCapabilityClient;
7018 bool isKernelCapabilityClient;
7019 IOReturn rc = kIOReturnError;
7020
7021 isSystemCapabilityClient = typeOfInterest &&
7022 typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
7023
7024 isKernelCapabilityClient = typeOfInterest &&
7025 typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
7026
7027 if (isSystemCapabilityClient) {
7028 typeOfInterest = gIOAppPowerStateInterest;
7029 }
7030
7031 notifier = new IOPMServiceInterestNotifier;
7032 if (!notifier) {
7033 return NULL;
7034 }
7035
7036 if (notifier->init()) {
7037 rc = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
7038 }
7039 if (rc != kIOReturnSuccess) {
7040 OSSafeReleaseNULL(notifier);
7041 return NULL;
7042 }
7043
7044 notifier->ackTimeoutCnt = 0;
7045
7046 if (pmPowerStateQueue) {
7047 if (isSystemCapabilityClient) {
7048 notifier->retain();
7049 if (pmPowerStateQueue->submitPowerEvent(
7050 kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
7051 notifier->release();
7052 }
7053 }
7054
7055 if (isKernelCapabilityClient) {
7056 notifier->retain();
7057 if (pmPowerStateQueue->submitPowerEvent(
7058 kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
7059 notifier->release();
7060 }
7061 }
7062 }
7063
7064 OSSharedPtr<OSData> data;
7065 uint8_t *uuid = NULL;
7066 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
7067 if (kext) {
7068 data = kext->copyUUID();
7069 }
7070 if (data && (data->getLength() == sizeof(uuid_t))) {
7071 uuid = (uint8_t *)(data->getBytesNoCopy());
7072
7073 notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
7074 ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
7075 ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
7076 notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
7077 ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
7078 ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
7079
7080 notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
7081 }
7082 return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
7083 }
7084
7085 //******************************************************************************
7086 // systemMessageFilter
7087 //
7088 //******************************************************************************
7089
7090 bool
7091 IOPMrootDomain::systemMessageFilter(
7092 void * object, void * arg1, void * arg2, void * arg3 )
7093 {
7094 const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
7095 bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
7096 bool isCapPowerd = (object == (void *) systemCapabilityNotifier.get());
7097 bool isCapClient = false;
7098 bool allow = false;
7099 OSBoolean **waitForReply = (typeof(waitForReply))arg3;
7100 IOPMServiceInterestNotifier *notifier;
7101
7102 notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
7103
7104 do {
7105 // When powerd and kernel priority clients register capability interest,
7106 // the power tree is sync'ed to inform those clients about the current
7107 // system capability. Only allow capability change messages during sync.
7108 if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
7109 (!isCapMsg || !_joinedCapabilityClients ||
7110 !_joinedCapabilityClients->containsObject((OSObject *) object))) {
7111 break;
7112 }
7113
7114 // Capability change message for powerd and kernel clients
7115 if (isCapMsg) {
7116 // Kernel priority clients
7117 if ((context->notifyType == kNotifyPriority) ||
7118 (context->notifyType == kNotifyCapabilityChangePriority)) {
7119 isCapClient = true;
7120 }
7121
7122 // powerd will maintain two client registrations with root domain.
7123 // isCapPowerd will be TRUE for any message targeting the powerd
7124 // exclusive (capability change) interest registration.
7125 if (isCapPowerd && (context->notifyType == kNotifyCapabilityChangeApps)) {
7126 isCapClient = true;
7127 }
7128 }
7129
7130 if (isCapClient) {
7131 IOPMSystemCapabilityChangeParameters * capArgs =
7132 (IOPMSystemCapabilityChangeParameters *) arg2;
7133
7134 if (kSystemTransitionNewCapClient == _systemTransitionType) {
7135 capArgs->fromCapabilities = 0;
7136 capArgs->toCapabilities = _currentCapability;
7137 capArgs->changeFlags = 0;
7138 } else {
7139 capArgs->fromCapabilities = _currentCapability;
7140 capArgs->toCapabilities = _pendingCapability;
7141
7142 if (context->isPreChange) {
7143 capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
7144 } else {
7145 capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
7146 }
7147
7148 if (isCapPowerd && context->isPreChange) {
7149 toldPowerdCapWillChange = true;
7150 }
7151 }
7152
7153 // App level capability change messages must only go to powerd.
7154 // Wait for response post-change if capabilitiy is increasing.
7155 // Wait for response pre-change if capability is decreasing.
7156
7157 if ((context->notifyType == kNotifyCapabilityChangeApps) && waitForReply &&
7158 ((capabilityLoss && context->isPreChange) ||
7159 (!capabilityLoss && !context->isPreChange))) {
7160 *waitForReply = kOSBooleanTrue;
7161 }
7162
7163 allow = true;
7164 break;
7165 }
7166
7167 // powerd will always receive CanSystemSleep, even for a demand sleep.
7168 // It will also have a final chance to veto sleep after all clients
7169 // have responded to SystemWillSleep
7170
7171 if ((kIOMessageCanSystemSleep == context->messageType) ||
7172 (kIOMessageSystemWillNotSleep == context->messageType)) {
7173 if (isCapPowerd) {
7174 allow = true;
7175 break;
7176 }
7177
7178 // Demand sleep, don't ask apps for permission
7179 if (context->changeFlags & kIOPMSkipAskPowerDown) {
7180 break;
7181 }
7182 }
7183
7184 if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
7185 if (isCapPowerd && CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
7186 (fullToDarkReason == kIOPMSleepReasonIdle)) {
7187 allow = true;
7188 }
7189 break;
7190 }
7191
7192 // Drop capability change messages for legacy clients.
7193 // Drop legacy system sleep messages for powerd capability interest.
7194 if (isCapMsg || isCapPowerd) {
7195 break;
7196 }
7197
7198 // Not a capability change message.
7199 // Perform message filtering based on _systemMessageClientMask.
7200
7201 if ((context->notifyType == kNotifyApps) &&
7202 (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7203 if (!notifier) {
7204 break;
7205 }
7206
7207 if ((notifier->lastSleepWakeMsgType == context->messageType) &&
7208 (notifier->lastSleepWakeMsgType == kIOMessageSystemWillPowerOn)) {
7209 break; // drop any duplicate WillPowerOn for AOT devices
7210 }
7211
7212 allow = true;
7213
7214 if (waitForReply) {
7215 if (notifier->ackTimeoutCnt >= 3) {
7216 *waitForReply = kOSBooleanFalse;
7217 } else {
7218 *waitForReply = kOSBooleanTrue;
7219 }
7220 }
7221 } else if ((context->notifyType == kNotifyPriority) &&
7222 (_systemMessageClientMask & kSystemMessageClientKernel)) {
7223 allow = true;
7224 }
7225
7226 // Check sleep/wake message ordering
7227 if (allow) {
7228 if (context->messageType == kIOMessageSystemWillSleep ||
7229 context->messageType == kIOMessageSystemWillPowerOn ||
7230 context->messageType == kIOMessageSystemHasPoweredOn) {
7231 notifier->lastSleepWakeMsgType = context->messageType;
7232 }
7233 }
7234 } while (false);
7235
7236 if (allow && isCapMsg && _joinedCapabilityClients) {
7237 _joinedCapabilityClients->removeObject((OSObject *) object);
7238 if (_joinedCapabilityClients->getCount() == 0) {
7239 DMSG("destroyed capability client set %p\n",
7240 OBFUSCATE(_joinedCapabilityClients.get()));
7241 _joinedCapabilityClients.reset();
7242 }
7243 }
7244 if (notifier) {
7245 // Record the last seen message type even if the message is dropped
7246 // for traceFilteredNotification().
7247 notifier->msgType = context->messageType;
7248 }
7249
7250 return allow;
7251 }
7252
7253 //******************************************************************************
7254 // setMaintenanceWakeCalendar
7255 //
7256 //******************************************************************************
7257
7258 IOReturn
7259 IOPMrootDomain::setMaintenanceWakeCalendar(
7260 const IOPMCalendarStruct * calendar )
7261 {
7262 OSSharedPtr<OSData> data;
7263 IOReturn ret = 0;
7264
7265 if (!calendar) {
7266 return kIOReturnBadArgument;
7267 }
7268
7269 data = OSData::withValue(*calendar);
7270 if (!data) {
7271 return kIOReturnNoMemory;
7272 }
7273
7274 if (kPMCalendarTypeMaintenance == calendar->selector) {
7275 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get());
7276 } else if (kPMCalendarTypeSleepService == calendar->selector) {
7277 ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get());
7278 }
7279
7280 return ret;
7281 }
7282
7283 // MARK: -
7284 // MARK: Display Wrangler
7285
7286 //******************************************************************************
7287 // displayWranglerNotification
7288 //
7289 // Handle the notification when the IODisplayWrangler changes power state.
7290 //******************************************************************************
7291
7292 IOReturn
7293 IOPMrootDomain::displayWranglerNotification(
7294 void * target, void * refCon,
7295 UInt32 messageType, IOService * service,
7296 void * messageArgument, vm_size_t argSize )
7297 {
7298 #if DISPLAY_WRANGLER_PRESENT
7299 IOPMPowerStateIndex displayPowerState;
7300 IOPowerStateChangeNotification * params =
7301 (IOPowerStateChangeNotification *) messageArgument;
7302
7303 if ((messageType != kIOMessageDeviceWillPowerOff) &&
7304 (messageType != kIOMessageDeviceHasPoweredOn)) {
7305 return kIOReturnUnsupported;
7306 }
7307
7308 ASSERT_GATED();
7309 if (!gRootDomain) {
7310 return kIOReturnUnsupported;
7311 }
7312
7313 displayPowerState = params->stateNumber;
7314 DLOG("wrangler %s ps %d\n",
7315 getIOMessageString(messageType), (uint32_t) displayPowerState);
7316
7317 switch (messageType) {
7318 case kIOMessageDeviceWillPowerOff:
7319 // Display wrangler has dropped power due to display idle
7320 // or force system sleep.
7321 //
7322 // 4 Display ON kWranglerPowerStateMax
7323 // 3 Display Dim kWranglerPowerStateDim
7324 // 2 Display Sleep kWranglerPowerStateSleep
7325 // 1 Not visible to user
7326 // 0 Not visible to user kWranglerPowerStateMin
7327
7328 if (displayPowerState <= kWranglerPowerStateSleep) {
7329 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7330 }
7331 break;
7332
7333 case kIOMessageDeviceHasPoweredOn:
7334 // Display wrangler has powered on due to user activity
7335 // or wake from sleep.
7336
7337 if (kWranglerPowerStateMax == displayPowerState) {
7338 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7339
7340 // See comment in handleUpdatePowerClientForDisplayWrangler
7341 if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7342 kWranglerPowerStateMax) {
7343 gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7344 }
7345 }
7346 break;
7347 }
7348 #endif /* DISPLAY_WRANGLER_PRESENT */
7349 return kIOReturnUnsupported;
7350 }
7351
7352 //******************************************************************************
7353 // reportUserInput
7354 //
7355 //******************************************************************************
7356
7357 void
7358 IOPMrootDomain::updateUserActivity( void )
7359 {
7360 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7361 clock_get_uptime(&userActivityTime);
7362 bool aborting = ((lastSleepReason == kIOPMSleepReasonSoftware)
7363 || (lastSleepReason == kIOPMSleepReasonIdle)
7364 || (lastSleepReason == kIOPMSleepReasonMaintenance));
7365 if (aborting) {
7366 userActivityCount++;
7367 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7368 }
7369 #endif
7370 }
7371 void
7372 IOPMrootDomain::reportUserInput( void )
7373 {
7374 if (wrangler) {
7375 wrangler->activityTickle(0, 0);
7376 }
7377 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7378 // Update user activity
7379 updateUserActivity();
7380
7381 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7382 // update user active abs time
7383 clock_get_uptime(&gUserActiveAbsTime);
7384 pmPowerStateQueue->submitPowerEvent(
7385 kPowerEventPolicyStimulus,
7386 (void *) kStimulusDarkWakeActivityTickle,
7387 true /* set wake type */ );
7388 }
7389 #endif
7390 }
7391
7392 void
7393 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7394 {
7395 #if DISPLAY_WRANGLER_PRESENT
7396 if (wrangler) {
7397 wrangler->activityTickle(0, 0);
7398 }
7399 #else
7400 if (!device) {
7401 DLOG("requestUserActive: device is null\n");
7402 return;
7403 }
7404 OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7405 uint64_t registryID = device->getRegistryEntryID();
7406
7407 if (!deviceName || !registryID) {
7408 DLOG("requestUserActive: no device name or registry entry\n");
7409 return;
7410 }
7411 const char *name = deviceName->getCStringNoCopy();
7412 char payload[128];
7413 snprintf(payload, sizeof(payload), "%s:%s", name, reason);
7414 DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason);
7415 messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload));
7416 #endif
7417 }
7418
7419 //******************************************************************************
7420 // latchDisplayWranglerTickle
7421 //******************************************************************************
7422
7423 bool
7424 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7425 {
7426 #if DISPLAY_WRANGLER_PRESENT
7427 if (latch) {
7428 if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
7429 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7430 !checkSystemCanSustainFullWake()) {
7431 // Currently in dark wake, and not transitioning to full wake.
7432 // Full wake is unsustainable, so latch the tickle to prevent
7433 // the display from lighting up momentarily.
7434 wranglerTickled = true;
7435 } else {
7436 wranglerTickled = false;
7437 }
7438 } else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7439 wranglerTickled = false;
7440
7441 pmPowerStateQueue->submitPowerEvent(
7442 kPowerEventPolicyStimulus,
7443 (void *) kStimulusDarkWakeActivityTickle );
7444 }
7445
7446 return wranglerTickled;
7447 #else /* ! DISPLAY_WRANGLER_PRESENT */
7448 return false;
7449 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7450 }
7451
7452 //******************************************************************************
7453 // setDisplayPowerOn
7454 //
7455 // For root domain user client
7456 //******************************************************************************
7457
7458 void
7459 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7460 {
7461 pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7462 (void *) NULL, options );
7463 }
7464
7465 // MARK: -
7466 // MARK: System PM Policy
7467
7468 //******************************************************************************
7469 // checkSystemSleepAllowed
7470 //
7471 //******************************************************************************
7472
7473 bool
7474 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7475 uint32_t sleepReason )
7476 {
7477 uint32_t err = 0;
7478
7479 // Conditions that prevent idle and demand system sleep.
7480
7481 do {
7482 if (gSleepDisabledFlag) {
7483 err = kPMConfigPreventSystemSleep;
7484 break;
7485 }
7486
7487 if (userDisabledAllSleep) {
7488 err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7489 break;
7490 }
7491
7492 if (systemBooting || systemShutdown || gWillShutdown) {
7493 err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7494 break;
7495 }
7496
7497 if (options == 0) {
7498 break;
7499 }
7500
7501 // Conditions above pegs the system at full wake.
7502 // Conditions below prevent system sleep but does not prevent
7503 // dark wake, and must be called from gated context.
7504
7505 #if !CONFIG_SLEEP
7506 err = kPMConfigPreventSystemSleep; // 3. config does not support sleep
7507 break;
7508 #endif
7509
7510 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7511 break; // always sleep on low battery or when in thermal warning/emergency state
7512 }
7513
7514 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7515 break; // always sleep on dark wake thermal emergencies
7516 }
7517
7518 if (preventSystemSleepList->getCount() != 0) {
7519 err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7520 break;
7521 }
7522
7523 if (_driverKitMatchingAssertionCount != 0) {
7524 err = kPMCPUAssertion;
7525 break;
7526 }
7527
7528 // Check for any dexts currently being added to the PM tree. Sleeping while
7529 // this is in flight can cause IOServicePH to timeout.
7530 if (!IOServicePH::checkPMReady()) {
7531 #if !defined(XNU_TARGET_OS_OSX)
7532 // 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
7533 // in dark wake for long periods of time, which causes issues as apps were
7534 // already informed of sleep during the f->9 transition. As a temporary
7535 // measure, always full wake if we hit this specific condition.
7536 pmPowerStateQueue->submitPowerEvent(
7537 kPowerEventPolicyStimulus,
7538 (void *) kStimulusDarkWakeActivityTickle);
7539 #endif
7540 err = kPMDKNotReady;
7541 break;
7542 }
7543
7544 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7545 kIOPMDriverAssertionLevelOn) {
7546 err = kPMCPUAssertion; // 5. CPU assertion
7547 break;
7548 }
7549
7550 if (pciCantSleepValid) {
7551 if (pciCantSleepFlag) {
7552 err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7553 }
7554 break;
7555 } else if (sleepSupportedPEFunction &&
7556 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7557 IOReturn ret;
7558 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7559 ret = getPlatform()->callPlatformFunction(
7560 sleepSupportedPEFunction.get(), false,
7561 NULL, NULL, NULL, NULL);
7562 pciCantSleepValid = true;
7563 pciCantSleepFlag = false;
7564 if ((platformSleepSupport & kPCICantSleep) ||
7565 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7566 err = 6; // 6. PCI card does not support PM
7567 pciCantSleepFlag = true;
7568 break;
7569 }
7570 }
7571 }while (false);
7572
7573 if (err) {
7574 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7575 return false;
7576 }
7577 return true;
7578 }
7579
7580 bool
7581 IOPMrootDomain::checkSystemSleepEnabled( void )
7582 {
7583 return checkSystemSleepAllowed(0, 0);
7584 }
7585
7586 bool
7587 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7588 {
7589 ASSERT_GATED();
7590 return checkSystemSleepAllowed(1, sleepReason);
7591 }
7592
7593 //******************************************************************************
7594 // checkSystemCanSustainFullWake
7595 //******************************************************************************
7596
7597 bool
7598 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7599 {
7600 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7601 // Low battery wake, or received a low battery notification
7602 // while system is awake. This condition will persist until
7603 // the following wake.
7604 return false;
7605 }
7606
7607 if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7608 // Graphics state is unknown and external display might not be probed.
7609 // Do not incorporate state that requires graphics to be in max power
7610 // such as desktopMode or clamshellDisabled.
7611
7612 if (!acAdaptorConnected) {
7613 DLOG("full wake check: no AC\n");
7614 return false;
7615 }
7616 }
7617 return true;
7618 }
7619
7620 //******************************************************************************
7621 // checkSystemCanAbortIdleSleep
7622 //******************************************************************************
7623
7624 bool
7625 IOPMrootDomain::checkSystemCanAbortIdleSleep( void )
7626 {
7627 bool abortableSleepType = ((lastSleepReason == kIOPMSleepReasonIdle)
7628 || (lastSleepReason == 0));
7629 return idleSleepRevertible && abortableSleepType;
7630 }
7631
7632 //******************************************************************************
7633 // attemptIdleSleepAbort
7634 //******************************************************************************
7635
7636 bool
7637 IOPMrootDomain::attemptIdleSleepAbort( void )
7638 {
7639 if (!gIOPMWorkLoop->inGate()) {
7640 bool ret = gIOPMWorkLoop->runAction(
7641 OSMemberFunctionCast(IOWorkLoop::Action, this,
7642 &IOPMrootDomain::attemptIdleSleepAbort),
7643 this);
7644 return ret;
7645 }
7646
7647 bool canAbort = checkSystemCanAbortIdleSleep();
7648 if (canAbort) {
7649 cancelIdlePowerDownSync();
7650 } else if (lastSleepReason == kIOPMSleepReasonIdle) {
7651 scheduleImmediateDebugWake();
7652 }
7653
7654 return canAbort;
7655 }
7656
7657 //******************************************************************************
7658 // setIdleSleepRevertible
7659 //******************************************************************************
7660
7661 void
7662 IOPMrootDomain::setIdleSleepRevertible( bool revertible )
7663 {
7664 idleSleepRevertible = revertible;
7665 }
7666
7667 //******************************************************************************
7668 // mustHibernate
7669 //******************************************************************************
7670
7671 #if HIBERNATION
7672
7673 bool
7674 IOPMrootDomain::mustHibernate( void )
7675 {
7676 return lowBatteryCondition || thermalWarningState;
7677 }
7678
7679 #endif /* HIBERNATION */
7680
7681 //******************************************************************************
7682 // AOT
7683 //******************************************************************************
7684
7685 // Tables for accumulated days in year by month, latter used for leap years
7686
7687 static const unsigned int daysbymonth[] =
7688 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7689
7690 static const unsigned int lydaysbymonth[] =
7691 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7692
7693 static int __unused
7694 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7695 {
7696 const unsigned int * dbm = daysbymonth;
7697 clock_sec_t n, x, y, z;
7698
7699 // Calculate seconds, minutes and hours
7700
7701 n = secs % (24 * 3600);
7702 dt->second = n % 60;
7703 n /= 60;
7704 dt->minute = n % 60;
7705 dt->hour = (typeof(dt->hour))(n / 60);
7706
7707 // Calculate day of week
7708
7709 n = secs / (24 * 3600);
7710 // dt->dayWeek = (n + 4) % 7;
7711
7712 // Calculate year
7713 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7714 // to days since 1/1/1968 to start on 4 year cycle, beginning
7715 // on a leap year.
7716
7717 n += (366 + 365);
7718
7719 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7720 // Valid before 2100, since 2100 is not a leap year.
7721
7722 x = n / 1461; // number of 4 year cycles
7723 y = n % 1461; // days into current 4 year cycle
7724 z = 1968 + (4 * x);
7725
7726 // Add in years in the current 4 year cycle
7727
7728 if (y >= 366) {
7729 y -= 366; // days after the leap year
7730 n = y % 365; // days into the current year
7731 z += (1 + y / 365); // years after the past 4-yr cycle
7732 } else {
7733 n = y;
7734 dbm = lydaysbymonth;
7735 }
7736 if (z > 2099) {
7737 return 0;
7738 }
7739
7740 dt->year = (typeof(dt->year))z;
7741
7742 // Adjust remaining days value to start at 1
7743
7744 n += 1;
7745
7746 // Calculate month
7747
7748 for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7749 continue;
7750 }
7751 dt->month = (typeof(dt->month))x;
7752
7753 // Calculate day of month
7754
7755 dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7756
7757 return 1;
7758 }
7759
7760 static clock_sec_t
7761 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7762 {
7763 const unsigned int * dbm = daysbymonth;
7764 long y, secs, days;
7765
7766 if (dt->year < 1970 || dt->month > 12) {
7767 return 0;
7768 }
7769
7770 // Seconds elapsed in the current day
7771
7772 secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7773
7774 // Number of days from 1/1/70 to beginning of current year
7775 // Account for extra day every 4 years starting at 1973
7776
7777 y = dt->year - 1970;
7778 days = (y * 365) + ((y + 1) / 4);
7779
7780 // Change table if current year is a leap year
7781
7782 if ((dt->year % 4) == 0) {
7783 dbm = lydaysbymonth;
7784 }
7785
7786 // Add in days elapsed in the current year
7787
7788 days += (dt->day - 1) + dbm[dt->month - 1];
7789
7790 // Add accumulated days to accumulated seconds
7791
7792 secs += 24 * 3600 * days;
7793
7794 return secs;
7795 }
7796
7797 unsigned long
7798 IOPMrootDomain::getRUN_STATE(void)
7799 {
7800 return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
7801 }
7802
7803 bool
7804 IOPMrootDomain::isAOTMode()
7805 {
7806 return _aotNow;
7807 }
7808
7809 IOReturn
7810 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7811 {
7812 clock_sec_t nowsecs, wakesecs;
7813 clock_usec_t nowmicrosecs, wakemicrosecs;
7814 uint64_t nowAbs, wakeAbs;
7815
7816 if (!_aotMode) {
7817 return kIOReturnNotReady;
7818 }
7819
7820 clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
7821 wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
7822 if (wakeAbs < nowAbs) {
7823 printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
7824 wakeAbs = nowAbs;
7825 }
7826 wakeAbs -= nowAbs;
7827 absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7828
7829 wakesecs += nowsecs;
7830 wakemicrosecs += nowmicrosecs;
7831 if (wakemicrosecs >= USEC_PER_SEC) {
7832 wakesecs++;
7833 wakemicrosecs -= USEC_PER_SEC;
7834 }
7835 if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7836 wakesecs++;
7837 }
7838
7839 IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7840
7841 if (_aotWakeTimeContinuous != wakeContinuousTime) {
7842 _aotWakeTimeContinuous = wakeContinuousTime;
7843 IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7844 }
7845 _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7846 _aotWakeTimeUTC = wakesecs;
7847
7848 return kIOReturnSuccess;
7849 }
7850
7851 // assumes WAKEEVENT_LOCK
7852 bool
7853 IOPMrootDomain::aotShouldExit(bool software)
7854 {
7855 bool exitNow = false;
7856 const char * reason = "";
7857
7858 if (!_aotNow) {
7859 return false;
7860 }
7861
7862 if (software) {
7863 exitNow = true;
7864 _aotMetrics->softwareRequestCount++;
7865 reason = "software request";
7866 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7867 exitNow = true;
7868 reason = gWakeReasonString;
7869 } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7870 clock_sec_t sec;
7871 clock_usec_t usec;
7872 clock_get_calendar_microtime(&sec, &usec);
7873 if (_calendarWakeAlarmUTC <= sec) {
7874 exitNow = true;
7875 _aotMetrics->rtcAlarmsCount++;
7876 reason = "user alarm";
7877 }
7878 }
7879 if (exitNow) {
7880 _aotPendingFlags |= kIOPMWakeEventAOTExit;
7881 IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7882 reason,
7883 _aotMetrics->sleepCount,
7884 _aotMetrics->possibleCount,
7885 _aotMetrics->confirmedPossibleCount,
7886 _aotMetrics->rejectedPossibleCount,
7887 _aotMetrics->expiredPossibleCount,
7888 _aotMetrics->noTimeSetCount,
7889 _aotMetrics->rtcAlarmsCount);
7890 }
7891 return exitNow;
7892 }
7893
7894 void
7895 IOPMrootDomain::aotExit(bool cps)
7896 {
7897 uint32_t savedMessageMask;
7898
7899 ASSERT_GATED();
7900 _aotNow = false;
7901 _aotReadyToFullWake = false;
7902 if (_aotTimerScheduled) {
7903 _aotTimerES->cancelTimeout();
7904 _aotTimerScheduled = false;
7905 }
7906 updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
7907
7908 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7909 _aotLastWakeTime = 0;
7910 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7911 WAKEEVENT_LOCK();
7912 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7913 gWakeReasonString,
7914 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7915 WAKEEVENT_UNLOCK();
7916 }
7917
7918 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7919
7920 // Preserve the message mask since a system wake transition
7921 // may have already started and initialized the mask.
7922 savedMessageMask = _systemMessageClientMask;
7923 _systemMessageClientMask = kSystemMessageClientLegacyApp;
7924 tellClients(kIOMessageSystemWillPowerOn);
7925 _systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
7926
7927 if (cps) {
7928 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7929 }
7930 }
7931
7932 void
7933 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7934 {
7935 bool exitNow;
7936
7937 IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7938
7939 WAKEEVENT_LOCK();
7940 exitNow = aotShouldExit(false);
7941 if (timer != NULL) {
7942 _aotTimerScheduled = false;
7943 }
7944 WAKEEVENT_UNLOCK();
7945 if (exitNow) {
7946 aotExit(true);
7947 } else {
7948 #if 0
7949 if (_aotLingerTime) {
7950 uint64_t deadline;
7951 IOLog("aot linger before sleep\n");
7952 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7953 clock_delay_until(deadline);
7954 }
7955 #endif
7956 privateSleepSystem(kIOPMSleepReasonSoftware);
7957 }
7958 }
7959
7960 //******************************************************************************
7961 // adjustPowerState
7962 //
7963 // Conditions that affect our wake/sleep decision has changed.
7964 // If conditions dictate that the system must remain awake, clamp power
7965 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7966 // is TRUE, then remove the power clamp and allow the power state to drop
7967 // to SLEEP_STATE.
7968 //******************************************************************************
7969
7970 void
7971 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7972 {
7973 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7974 getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7975
7976 ASSERT_GATED();
7977
7978 if (_aotNow) {
7979 bool exitNow;
7980
7981 if (AOT_STATE != getPowerState()) {
7982 return;
7983 }
7984 WAKEEVENT_LOCK();
7985 exitNow = aotShouldExit(false);
7986 if (!exitNow
7987 && !_aotTimerScheduled
7988 && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
7989 _aotTimerScheduled = true;
7990 if (_aotLingerTime) {
7991 _aotTimerES->setTimeout(_aotLingerTime);
7992 } else {
7993 _aotTimerES->setTimeout(800, kMillisecondScale);
7994 }
7995 }
7996 WAKEEVENT_UNLOCK();
7997 if (exitNow) {
7998 aotExit(true);
7999 } else {
8000 _aotReadyToFullWake = true;
8001 if (!_aotTimerScheduled) {
8002 if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
8003 // Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
8004 // Doing so will result in the sleep being cancelled anyway,
8005 // but this check avoids unnecessary thrashing in the power state engine.
8006 return;
8007 }
8008 privateSleepSystem(kIOPMSleepReasonSoftware);
8009 }
8010 }
8011 return;
8012 }
8013
8014 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
8015 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
8016 } else if (sleepASAP) {
8017 changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
8018 }
8019 }
8020
8021 void
8022 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
8023 {
8024 if (powerOn) {
8025 if (!checkSystemCanSustainFullWake()) {
8026 DLOG("System cannot sustain full wake\n");
8027 return;
8028 }
8029
8030 // Force wrangler to max power state. If system is in dark wake
8031 // this alone won't raise the wrangler's power state.
8032 if (wrangler) {
8033 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
8034 }
8035
8036 // System in dark wake, always requesting full wake should
8037 // not have any bad side-effects, even if the request fails.
8038
8039 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8040 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
8041 requestFullWake( kFullWakeReasonDisplayOn );
8042 }
8043 } else {
8044 // Relenquish desire to power up display.
8045 // Must first transition to state 1 since wrangler doesn't
8046 // power off the displays at state 0. At state 0 the root
8047 // domain is removed from the wrangler's power client list.
8048 if (wrangler) {
8049 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
8050 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
8051 }
8052 }
8053 }
8054
8055 TUNABLE(bool, test_sleep_in_vm, "test_sleep_in_vm", false);
8056
8057 //******************************************************************************
8058 // dispatchPowerEvent
8059 //
8060 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
8061 //******************************************************************************
8062
8063 void
8064 IOPMrootDomain::dispatchPowerEvent(
8065 uint32_t event, void * arg0, uint64_t arg1 )
8066 {
8067 ASSERT_GATED();
8068
8069 switch (event) {
8070 case kPowerEventFeatureChanged:
8071 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8072 messageClients(kIOPMMessageFeatureChange, this);
8073 break;
8074
8075 case kPowerEventReceivedPowerNotification:
8076 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8077 handlePowerNotification((UInt32)(uintptr_t) arg0 );
8078 break;
8079
8080 case kPowerEventSystemBootCompleted:
8081 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8082 if (systemBooting) {
8083 systemBooting = false;
8084
8085 if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
8086 DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
8087 if (test_sleep_in_vm && gSleepDisabledFlag) {
8088 DLOG("Clearing gSleepDisabledFlag due to test_sleep_in_vm boot-arg\n");
8089 gSleepDisabledFlag = 0;
8090 }
8091 }
8092
8093 if (lowBatteryCondition || thermalEmergencyState) {
8094 if (lowBatteryCondition) {
8095 privateSleepSystem(kIOPMSleepReasonLowPower);
8096 } else {
8097 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8098 }
8099 // The rest is unnecessary since the system is expected
8100 // to sleep immediately. The following wake will update
8101 // everything.
8102 break;
8103 }
8104
8105 sleepWakeDebugMemAlloc();
8106 saveFailureData2File();
8107
8108 // If lid is closed, re-send lid closed notification
8109 // now that booting is complete.
8110 if (clamshellClosed) {
8111 handlePowerNotification(kLocalEvalClamshellCommand);
8112 }
8113 evaluatePolicy( kStimulusAllowSystemSleepChanged );
8114 }
8115 break;
8116
8117 case kPowerEventSystemShutdown:
8118 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8119 if (kOSBooleanTrue == (OSBoolean *) arg0) {
8120 /* We set systemShutdown = true during shutdown
8121 * to prevent sleep at unexpected times while loginwindow is trying
8122 * to shutdown apps and while the OS is trying to transition to
8123 * complete power of.
8124 *
8125 * Set to true during shutdown, as soon as loginwindow shows
8126 * the "shutdown countdown dialog", through individual app
8127 * termination, and through black screen kernel shutdown.
8128 */
8129 systemShutdown = true;
8130 } else {
8131 /*
8132 * A shutdown was initiated, but then the shutdown
8133 * was cancelled, clearing systemShutdown to false here.
8134 */
8135 systemShutdown = false;
8136 }
8137 break;
8138
8139 case kPowerEventUserDisabledSleep:
8140 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8141 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8142 break;
8143
8144 case kPowerEventRegisterSystemCapabilityClient:
8145 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8146
8147 // reset() handles the arg0 == nullptr case for us
8148 systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8149 /* intentional fall-through */
8150 [[clang::fallthrough]];
8151
8152 case kPowerEventRegisterKernelCapabilityClient:
8153 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8154 if (!_joinedCapabilityClients) {
8155 _joinedCapabilityClients = OSSet::withCapacity(8);
8156 }
8157 if (arg0) {
8158 OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8159 if (_joinedCapabilityClients) {
8160 _joinedCapabilityClients->setObject(notify.get());
8161 synchronizePowerTree( kIOPMSyncNoChildNotify );
8162 }
8163 }
8164 break;
8165
8166 case kPowerEventPolicyStimulus:
8167 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8168 if (arg0) {
8169 int stimulus = (int)(uintptr_t) arg0;
8170 evaluatePolicy(stimulus, (uint32_t) arg1);
8171 }
8172 break;
8173
8174 case kPowerEventAssertionCreate:
8175 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8176 if (pmAssertions) {
8177 pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8178 }
8179 break;
8180
8181
8182 case kPowerEventAssertionRelease:
8183 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8184 if (pmAssertions) {
8185 pmAssertions->handleReleaseAssertion(arg1);
8186 }
8187 break;
8188
8189 case kPowerEventAssertionSetLevel:
8190 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8191 if (pmAssertions) {
8192 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8193 }
8194 break;
8195
8196 case kPowerEventQueueSleepWakeUUID:
8197 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8198 handleQueueSleepWakeUUID((OSObject *)arg0);
8199 break;
8200 case kPowerEventPublishSleepWakeUUID:
8201 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8202 handlePublishSleepWakeUUID((bool)arg0);
8203 break;
8204
8205 case kPowerEventSetDisplayPowerOn:
8206 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8207 if (arg1 != 0) {
8208 displayPowerOnRequested = true;
8209 } else {
8210 displayPowerOnRequested = false;
8211 }
8212 handleSetDisplayPowerOn(displayPowerOnRequested);
8213 break;
8214
8215 case kPowerEventPublishWakeType:
8216 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8217
8218 // Don't replace wake type property if already set
8219 if ((arg0 == gIOPMWakeTypeUserKey) ||
8220 !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8221 const char * wakeType = NULL;
8222
8223 if (arg0 == gIOPMWakeTypeUserKey) {
8224 requestUserActive(this, "WakeTypeUser");
8225 wakeType = kIOPMRootDomainWakeTypeUser;
8226 } else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8227 if (!(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
8228 requestUserActive(this, "WakeTypeAlarm");
8229 }
8230 wakeType = kIOPMRootDomainWakeTypeAlarm;
8231 } else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8232 darkWakeSleepService = true;
8233 wakeType = kIOPMRootDomainWakeTypeSleepService;
8234 } else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8235 wakeType = kIOPMRootDomainWakeTypeMaintenance;
8236 }
8237
8238 if (wakeType) {
8239 setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8240 }
8241 }
8242 break;
8243
8244 case kPowerEventAOTEvaluate:
8245 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8246 if (_aotReadyToFullWake) {
8247 aotEvaluate(NULL);
8248 }
8249 break;
8250 }
8251 }
8252
8253 //******************************************************************************
8254 // systemPowerEventOccurred
8255 //
8256 // The power controller is notifying us of a hardware-related power management
8257 // event that we must handle.
8258 //
8259 // systemPowerEventOccurred covers the same functionality that
8260 // receivePowerNotification does; it simply provides a richer API for conveying
8261 // more information.
8262 //******************************************************************************
8263
8264 IOReturn
8265 IOPMrootDomain::systemPowerEventOccurred(
8266 const OSSymbol *event,
8267 uint32_t intValue)
8268 {
8269 IOReturn attempt = kIOReturnSuccess;
8270 OSSharedPtr<OSNumber> newNumber;
8271
8272 if (!event) {
8273 return kIOReturnBadArgument;
8274 }
8275
8276 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8277 if (!newNumber) {
8278 return kIOReturnInternalError;
8279 }
8280
8281 attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8282
8283 return attempt;
8284 }
8285
8286 void
8287 IOPMrootDomain::setThermalState(OSObject *value)
8288 {
8289 OSNumber * num;
8290
8291 if (gIOPMWorkLoop->inGate() == false) {
8292 gIOPMWorkLoop->runAction(
8293 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8294 (OSObject *)this,
8295 (void *)value);
8296
8297 return;
8298 }
8299 if (value && (num = OSDynamicCast(OSNumber, value))) {
8300 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8301 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8302 }
8303 }
8304
8305 IOReturn
8306 IOPMrootDomain::systemPowerEventOccurred(
8307 const OSSymbol *event,
8308 OSObject *value)
8309 {
8310 OSSharedPtr<OSDictionary> thermalsDict;
8311 bool shouldUpdate = true;
8312
8313 if (!event || !value) {
8314 return kIOReturnBadArgument;
8315 }
8316
8317 // LOCK
8318 // We reuse featuresDict Lock because it already exists and guards
8319 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
8320 // of stepping on that lock.
8321 if (featuresDictLock) {
8322 IOLockLock(featuresDictLock);
8323 }
8324
8325 OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8326 OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8327
8328 if (origThermalsDict) {
8329 thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8330 } else {
8331 thermalsDict = OSDictionary::withCapacity(1);
8332 }
8333
8334 if (!thermalsDict) {
8335 shouldUpdate = false;
8336 goto exit;
8337 }
8338
8339 thermalsDict->setObject(event, value);
8340
8341 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8342
8343 exit:
8344 // UNLOCK
8345 if (featuresDictLock) {
8346 IOLockUnlock(featuresDictLock);
8347 }
8348
8349 if (shouldUpdate) {
8350 if (event &&
8351 event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8352 setThermalState(value);
8353 }
8354 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8355 }
8356
8357 return kIOReturnSuccess;
8358 }
8359
8360 //******************************************************************************
8361 // receivePowerNotification
8362 //
8363 // The power controller is notifying us of a hardware-related power management
8364 // event that we must handle. This may be a result of an 'environment' interrupt
8365 // from the power mgt micro.
8366 //******************************************************************************
8367
8368 IOReturn
8369 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8370 {
8371 if (msg & kIOPMPowerButton) {
8372 uint32_t currentPhase = pmTracer->getTracePhase();
8373 if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8374 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8375 swd_flags |= SWD_PWR_BTN_STACKSHOT;
8376 thread_call_enter(powerButtonDown);
8377 } else {
8378 DEBUG_LOG("power button pressed when system is up\n");
8379 }
8380 } else if (msg & kIOPMPowerButtonUp) {
8381 if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8382 swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8383 thread_call_enter(powerButtonUp);
8384 }
8385 } else {
8386 pmPowerStateQueue->submitPowerEvent(
8387 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8388 }
8389 return kIOReturnSuccess;
8390 }
8391
8392 void
8393 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8394 {
8395 bool eval_clamshell = false;
8396 bool eval_clamshell_alarm = false;
8397
8398 ASSERT_GATED();
8399
8400 /*
8401 * Local (IOPMrootDomain only) eval clamshell command
8402 */
8403 if (msg & kLocalEvalClamshellCommand) {
8404 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8405 eval_clamshell_alarm = true;
8406
8407 // reset isRTCAlarmWake. This evaluation should happen only once
8408 // on RTC/Alarm wake. Any clamshell events after wake should follow
8409 // the regular evaluation
8410 isRTCAlarmWake = false;
8411 } else {
8412 eval_clamshell = true;
8413 }
8414 }
8415
8416 /*
8417 * Overtemp
8418 */
8419 if (msg & kIOPMOverTemp) {
8420 DLOG("Thermal overtemp message received!\n");
8421 thermalEmergencyState = true;
8422 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8423 }
8424
8425 /*
8426 * Forward DW thermal notification to client, if system is not going to sleep
8427 */
8428 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8429 DLOG("DarkWake thermal limits message received!\n");
8430 messageClients(kIOPMMessageDarkWakeThermalEmergency);
8431 }
8432
8433 /*
8434 * Sleep Now!
8435 */
8436 if (msg & kIOPMSleepNow) {
8437 privateSleepSystem(kIOPMSleepReasonSoftware);
8438 }
8439
8440 /*
8441 * Power Emergency
8442 */
8443 if (msg & kIOPMPowerEmergency) {
8444 DLOG("Received kIOPMPowerEmergency");
8445 #if HIBERNATION && defined(__arm64__)
8446 if (!ml_is_secure_hib_supported()) {
8447 // Wait for the next low battery notification if the system state is
8448 // in transition.
8449 if ((_systemTransitionType == kSystemTransitionNone) &&
8450 CAP_CURRENT(kIOPMSystemCapabilityCPU) &&
8451 !systemBooting && !systemShutdown && !gWillShutdown) {
8452 // Setting lowBatteryCondition will prevent system sleep
8453 lowBatteryCondition = true;
8454
8455 // Notify userspace to initiate system shutdown
8456 messageClients(kIOPMMessageRequestSystemShutdown);
8457 }
8458 } else {
8459 lowBatteryCondition = true;
8460 privateSleepSystem(kIOPMSleepReasonLowPower);
8461 }
8462 #else /* HIBERNATION && defined(__arm64__) */
8463 lowBatteryCondition = true;
8464 privateSleepSystem(kIOPMSleepReasonLowPower);
8465 #endif /* HIBERNATION && defined(__arm64__) */
8466 }
8467
8468 /*
8469 * Clamshell OPEN
8470 */
8471 if (msg & kIOPMClamshellOpened) {
8472 DLOG("Clamshell opened\n");
8473 // Received clamshel open message from clamshell controlling driver
8474 // Update our internal state and tell general interest clients
8475 clamshellClosed = false;
8476 clamshellExists = true;
8477
8478 // Don't issue a hid tickle when lid is open and polled on wake
8479 if (msg & kIOPMSetValue) {
8480 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8481 reportUserInput();
8482 }
8483
8484 // Tell PMCPU
8485 informCPUStateChange(kInformLid, 0);
8486
8487 // Tell general interest clients
8488 sendClientClamshellNotification();
8489
8490 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
8491 || (lastSleepReason == kIOPMSleepReasonIdle)
8492 || (lastSleepReason == kIOPMSleepReasonMaintenance));
8493 if (aborting) {
8494 userActivityCount++;
8495 }
8496 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8497 }
8498
8499 /*
8500 * Clamshell CLOSED
8501 * Send the clamshell interest notification since the lid is closing.
8502 */
8503 if (msg & kIOPMClamshellClosed) {
8504 if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8505 clamshellClosed && clamshellExists) {
8506 DLOG("Ignoring redundant Clamshell close event\n");
8507 } else {
8508 DLOG("Clamshell closed\n");
8509 // Received clamshel open message from clamshell controlling driver
8510 // Update our internal state and tell general interest clients
8511 clamshellClosed = true;
8512 clamshellExists = true;
8513
8514 // Ignore all following clamshell close events until the clamshell
8515 // is opened or the system sleeps. When a clamshell close triggers
8516 // a system wake, the lid driver may send us two clamshell close
8517 // events, one for the clamshell close event itself, and a second
8518 // close event when the driver polls the lid state on wake.
8519 clamshellIgnoreClose = true;
8520
8521 // Tell PMCPU
8522 informCPUStateChange(kInformLid, 1);
8523
8524 // Tell general interest clients
8525 sendClientClamshellNotification();
8526
8527 // And set eval_clamshell = so we can attempt
8528 eval_clamshell = true;
8529 }
8530 }
8531
8532 /*
8533 * Set Desktop mode (sent from graphics)
8534 *
8535 * -> reevaluate lid state
8536 */
8537 if (msg & kIOPMSetDesktopMode) {
8538 desktopMode = (0 != (msg & kIOPMSetValue));
8539 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8540 DLOG("Desktop mode %d\n", desktopMode);
8541
8542 sendClientClamshellNotification();
8543
8544 // Re-evaluate the lid state
8545 eval_clamshell = true;
8546 }
8547
8548 /*
8549 * AC Adaptor connected
8550 *
8551 * -> reevaluate lid state
8552 */
8553 if (msg & kIOPMSetACAdaptorConnected) {
8554 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8555 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8556
8557 // Tell CPU PM
8558 informCPUStateChange(kInformAC, !acAdaptorConnected);
8559
8560 // Tell BSD if AC is connected
8561 // 0 == external power source; 1 == on battery
8562 post_sys_powersource(acAdaptorConnected ? 0:1);
8563
8564 sendClientClamshellNotification();
8565
8566 IOUserServer::powerSourceChanged(acAdaptorConnected);
8567
8568 // Re-evaluate the lid state
8569 eval_clamshell = true;
8570
8571 // Lack of AC may have latched a display wrangler tickle.
8572 // This mirrors the hardware's USB wake event latch, where a latched
8573 // USB wake event followed by an AC attach will trigger a full wake.
8574 latchDisplayWranglerTickle( false );
8575
8576 #if HIBERNATION
8577 // AC presence will reset the standy timer delay adjustment.
8578 _standbyTimerResetSeconds = 0;
8579 #endif
8580 if (!userIsActive) {
8581 // Reset userActivityTime when power supply is changed(rdr 13789330)
8582 clock_get_uptime(&userActivityTime);
8583 }
8584 }
8585
8586 /*
8587 * Enable Clamshell (external display disappear)
8588 *
8589 * -> reevaluate lid state
8590 */
8591 if (msg & kIOPMEnableClamshell) {
8592 DLOG("Clamshell enabled\n");
8593
8594 // Re-evaluate the lid state
8595 // System should sleep on external display disappearance
8596 // in lid closed operation.
8597 if (true == clamshellDisabled) {
8598 eval_clamshell = true;
8599
8600 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8601 // Also clear kClamshellSleepDisableInternal when graphics enables
8602 // the clamshell during a full wake. When graphics is behaving as
8603 // expected, this will allow clamshell close to be honored earlier
8604 // rather than waiting for the delayed evaluation.
8605 if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8606 (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8607 CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8608 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8609
8610 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8611 // when timer expires which is harmless but useless.
8612 thread_call_cancel(fullWakeThreadCall);
8613 }
8614 #endif
8615 }
8616
8617 clamshellDisabled = false;
8618 sendClientClamshellNotification();
8619 }
8620
8621 /*
8622 * Disable Clamshell (external display appeared)
8623 * We don't bother re-evaluating clamshell state. If the system is awake,
8624 * the lid is probably open.
8625 */
8626 if (msg & kIOPMDisableClamshell) {
8627 DLOG("Clamshell disabled\n");
8628 clamshellDisabled = true;
8629 sendClientClamshellNotification();
8630 }
8631
8632 /*
8633 * Evaluate clamshell and SLEEP if appropriate
8634 */
8635 if (eval_clamshell_alarm && clamshellClosed) {
8636 if (shouldSleepOnRTCAlarmWake()) {
8637 privateSleepSystem(kIOPMSleepReasonClamshell);
8638 }
8639 } else if (eval_clamshell && clamshellClosed) {
8640 if (shouldSleepOnClamshellClosed()) {
8641 privateSleepSystem(kIOPMSleepReasonClamshell);
8642 } else {
8643 evaluatePolicy( kStimulusDarkWakeEvaluate );
8644 }
8645 }
8646
8647 if (msg & kIOPMProModeEngaged) {
8648 int newState = 1;
8649 DLOG("ProModeEngaged\n");
8650 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8651 }
8652
8653 if (msg & kIOPMProModeDisengaged) {
8654 int newState = 0;
8655 DLOG("ProModeDisengaged\n");
8656 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8657 }
8658 }
8659
8660 //******************************************************************************
8661 // evaluatePolicy
8662 //
8663 // Evaluate root-domain policy in response to external changes.
8664 //******************************************************************************
8665
8666 void
8667 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8668 {
8669 union {
8670 struct {
8671 int idleSleepEnabled : 1;
8672 int idleSleepDisabled : 1;
8673 int displaySleep : 1;
8674 int sleepDelayChanged : 1;
8675 int evaluateDarkWake : 1;
8676 int adjustPowerState : 1;
8677 int userBecameInactive : 1;
8678 int displaySleepEntry : 1;
8679 } bit;
8680 uint32_t u32;
8681 } flags;
8682
8683
8684 ASSERT_GATED();
8685 flags.u32 = 0;
8686
8687 switch (stimulus) {
8688 case kStimulusDisplayWranglerSleep:
8689 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8690 if (!wranglerPowerOff) {
8691 // wrangler is in sleep state or lower
8692 flags.bit.displaySleep = true;
8693 }
8694 if (!wranglerAsleep) {
8695 // transition from wrangler wake to wrangler sleep
8696 flags.bit.displaySleepEntry = true;
8697 wranglerAsleep = true;
8698 }
8699 break;
8700
8701 case kStimulusDisplayWranglerWake:
8702 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8703 displayIdleForDemandSleep = false;
8704 wranglerPowerOff = false;
8705 wranglerAsleep = false;
8706 break;
8707
8708 case kStimulusEnterUserActiveState:
8709 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8710 if (_preventUserActive) {
8711 DLOG("user active dropped\n");
8712 break;
8713 }
8714 if (!userIsActive) {
8715 userIsActive = true;
8716 userWasActive = true;
8717 clock_get_uptime(&gUserActiveAbsTime);
8718
8719 // Stay awake after dropping demand for display power on
8720 if (kFullWakeReasonDisplayOn == fullWakeReason) {
8721 fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8722 DLOG("User activity while in notification wake\n");
8723 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8724 }
8725
8726 kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8727 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8728 messageClients(kIOPMMessageUserIsActiveChanged);
8729 }
8730 flags.bit.idleSleepDisabled = true;
8731 break;
8732
8733 case kStimulusLeaveUserActiveState:
8734 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8735 if (userIsActive) {
8736 clock_get_uptime(&gUserInactiveAbsTime);
8737 userIsActive = false;
8738 clock_get_uptime(&userBecameInactiveTime);
8739 flags.bit.userBecameInactive = true;
8740
8741 kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8742 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8743 messageClients(kIOPMMessageUserIsActiveChanged);
8744 }
8745 break;
8746
8747 case kStimulusAggressivenessChanged:
8748 {
8749 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8750 unsigned long aggressiveValue;
8751 uint32_t minutesToIdleSleep = 0;
8752 uint32_t minutesToDisplayDim = 0;
8753 uint32_t minutesDelta = 0;
8754
8755 // Fetch latest display and system sleep slider values.
8756 aggressiveValue = 0;
8757 getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8758 minutesToIdleSleep = (uint32_t) aggressiveValue;
8759
8760 aggressiveValue = 0;
8761 getAggressiveness(kPMMinutesToDim, &aggressiveValue);
8762 minutesToDisplayDim = (uint32_t) aggressiveValue;
8763 DLOG("aggressiveness changed: system %u->%u, display %u\n",
8764 sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
8765
8766 DLOG("idle time -> %d ms (ena %d)\n",
8767 idleMilliSeconds, (minutesToIdleSleep != 0));
8768
8769 // How long to wait before sleeping the system once
8770 // the displays turns off is indicated by 'extraSleepDelay'.
8771
8772 if (minutesToIdleSleep > minutesToDisplayDim) {
8773 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8774 } else if (minutesToIdleSleep == minutesToDisplayDim) {
8775 minutesDelta = 1;
8776 }
8777
8778 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8779 idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8780 }
8781
8782 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8783 flags.bit.idleSleepDisabled = true;
8784 idleSleepEnabled = false;
8785 }
8786 #if !defined(XNU_TARGET_OS_OSX)
8787 if (0x7fffffff == minutesToIdleSleep) {
8788 minutesToIdleSleep = idleMilliSeconds / 1000;
8789 }
8790 #endif /* !defined(XNU_TARGET_OS_OSX) */
8791
8792 if (((minutesDelta != extraSleepDelay) ||
8793 (userActivityTime != userActivityTime_prev)) &&
8794 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8795 flags.bit.sleepDelayChanged = true;
8796 }
8797
8798 if (systemDarkWake && !darkWakeToSleepASAP &&
8799 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8800 // Reconsider decision to remain in dark wake
8801 flags.bit.evaluateDarkWake = true;
8802 }
8803
8804 sleepSlider = minutesToIdleSleep;
8805 extraSleepDelay = minutesDelta;
8806 userActivityTime_prev = userActivityTime;
8807 } break;
8808
8809 case kStimulusDemandSystemSleep:
8810 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8811 displayIdleForDemandSleep = true;
8812 if (wrangler && wranglerIdleSettings) {
8813 // Request wrangler idle only when demand sleep is triggered
8814 // from full wake.
8815 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8816 wrangler->setProperties(wranglerIdleSettings.get());
8817 DLOG("Requested wrangler idle\n");
8818 }
8819 }
8820 // arg = sleepReason
8821 changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8822 break;
8823
8824 case kStimulusAllowSystemSleepChanged:
8825 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8826 flags.bit.adjustPowerState = true;
8827 break;
8828
8829 case kStimulusDarkWakeActivityTickle:
8830 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8831 // arg == true implies real and not self generated wrangler tickle.
8832 // Update wake type on PM work loop instead of the tickle thread to
8833 // eliminate the possibility of an early tickle clobbering the wake
8834 // type set by the platform driver.
8835 if (arg == true) {
8836 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8837 }
8838
8839 if (!darkWakeExit) {
8840 if (latchDisplayWranglerTickle(true)) {
8841 DLOG("latched tickle\n");
8842 break;
8843 }
8844
8845 darkWakeExit = true;
8846 DLOG("Requesting full wake due to dark wake activity tickle\n");
8847 requestFullWake( kFullWakeReasonLocalUser );
8848 }
8849 break;
8850
8851 case kStimulusDarkWakeEntry:
8852 case kStimulusDarkWakeReentry:
8853 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8854 // Any system transitions since the last dark wake transition
8855 // will invalid the stimulus.
8856
8857 if (arg == _systemStateGeneration) {
8858 DLOG("dark wake entry\n");
8859 systemDarkWake = true;
8860
8861 // Keep wranglerPowerOff an invariant when wrangler is absent
8862 if (wrangler) {
8863 wranglerPowerOff = true;
8864 }
8865
8866 if (kStimulusDarkWakeEntry == stimulus) {
8867 clock_get_uptime(&userBecameInactiveTime);
8868 flags.bit.evaluateDarkWake = true;
8869 if (activitySinceSleep()) {
8870 DLOG("User activity recorded while going to darkwake\n");
8871 reportUserInput();
8872 }
8873 }
8874
8875 // Always accelerate disk spindown while in dark wake,
8876 // even if system does not support/allow sleep.
8877
8878 cancelIdleSleepTimer();
8879 setQuickSpinDownTimeout();
8880 }
8881 break;
8882
8883 case kStimulusDarkWakeEvaluate:
8884 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8885 if (systemDarkWake) {
8886 flags.bit.evaluateDarkWake = true;
8887 }
8888 break;
8889
8890 case kStimulusNoIdleSleepPreventers:
8891 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8892 flags.bit.adjustPowerState = true;
8893 break;
8894 } /* switch(stimulus) */
8895
8896 if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
8897 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8898 darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
8899 if (darkWakeToSleepASAP ||
8900 (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
8901 uint32_t newSleepReason;
8902
8903 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8904 // System was previously in full wake. Sleep reason from
8905 // full to dark already recorded in fullToDarkReason.
8906
8907 if (lowBatteryCondition) {
8908 newSleepReason = kIOPMSleepReasonLowPower;
8909 } else if (thermalEmergencyState) {
8910 newSleepReason = kIOPMSleepReasonThermalEmergency;
8911 } else {
8912 newSleepReason = fullToDarkReason;
8913 }
8914 } else {
8915 // In dark wake from system sleep.
8916
8917 if (darkWakeSleepService) {
8918 newSleepReason = kIOPMSleepReasonSleepServiceExit;
8919 } else {
8920 newSleepReason = kIOPMSleepReasonMaintenance;
8921 }
8922 }
8923
8924 if (checkSystemCanSleep(newSleepReason)) {
8925 privateSleepSystem(newSleepReason);
8926 }
8927 } else { // non-maintenance (network) dark wake
8928 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8929 // Release power clamp, and wait for children idle.
8930 adjustPowerState(true);
8931 } else {
8932 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8933 }
8934 }
8935 }
8936
8937 if (systemDarkWake) {
8938 // The rest are irrelevant while system is in dark wake.
8939 flags.u32 = 0;
8940 }
8941
8942 if ((flags.bit.displaySleepEntry) &&
8943 (kFullWakeReasonDisplayOn == fullWakeReason)) {
8944 // kIOPMSleepReasonNotificationWakeExit
8945 DLOG("Display sleep while in notification wake\n");
8946 changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8947 }
8948
8949 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8950 bool cancelQuickSpindown = false;
8951
8952 if (flags.bit.sleepDelayChanged) {
8953 // Cancel existing idle sleep timer and quick disk spindown.
8954 // New settings will be applied by the idleSleepEnabled flag
8955 // handler below if idle sleep is enabled.
8956
8957 DLOG("extra sleep timer changed\n");
8958 cancelIdleSleepTimer();
8959 cancelQuickSpindown = true;
8960 } else {
8961 DLOG("user inactive\n");
8962 }
8963
8964 if (!userIsActive && idleSleepEnabled) {
8965 startIdleSleepTimer(getTimeToIdleSleep());
8966 }
8967
8968 if (cancelQuickSpindown) {
8969 restoreUserSpinDownTimeout();
8970 }
8971 }
8972
8973 if (flags.bit.idleSleepEnabled) {
8974 DLOG("idle sleep timer enabled\n");
8975 if (!wrangler) {
8976 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8977 startIdleSleepTimer(getTimeToIdleSleep());
8978 #else
8979 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8980 startIdleSleepTimer( idleMilliSeconds );
8981 #endif
8982 } else {
8983 // Start idle timer if prefs now allow system sleep
8984 // and user is already inactive. Disk spindown is
8985 // accelerated upon timer expiration.
8986
8987 if (!userIsActive) {
8988 startIdleSleepTimer(getTimeToIdleSleep());
8989 }
8990 }
8991 }
8992
8993 if (flags.bit.idleSleepDisabled) {
8994 DLOG("idle sleep timer disabled\n");
8995 cancelIdleSleepTimer();
8996 restoreUserSpinDownTimeout();
8997 adjustPowerState();
8998 }
8999
9000 if (flags.bit.adjustPowerState) {
9001 bool sleepASAP = false;
9002
9003 if (!systemBooting && (0 == idleSleepPreventersCount())) {
9004 if (!wrangler) {
9005 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
9006 if (idleSleepEnabled) {
9007 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
9008 if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
9009 sleepASAP = true;
9010 }
9011 #else
9012 // stay awake for at least idleMilliSeconds
9013 startIdleSleepTimer(idleMilliSeconds);
9014 #endif
9015 }
9016 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
9017 sleepASAP = true;
9018 }
9019 }
9020
9021 adjustPowerState(sleepASAP);
9022 }
9023 }
9024
9025 //******************************************************************************
9026
9027 unsigned int
9028 IOPMrootDomain::idleSleepPreventersCount()
9029 {
9030 if (_aotMode) {
9031 unsigned int count __block;
9032 count = 0;
9033 preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
9034 {
9035 count += (NULL == obj->metaCast("AppleARMBacklight"));
9036 return false;
9037 });
9038 return count;
9039 }
9040
9041 return preventIdleSleepList->getCount();
9042 }
9043
9044
9045 //******************************************************************************
9046 // requestFullWake
9047 //
9048 // Request transition from dark wake to full wake
9049 //******************************************************************************
9050
9051 void
9052 IOPMrootDomain::requestFullWake( FullWakeReason reason )
9053 {
9054 uint32_t options = 0;
9055 IOService * pciRoot = NULL;
9056 bool promotion = false;
9057
9058 // System must be in dark wake and a valid reason for entering full wake
9059 if ((kFullWakeReasonNone == reason) ||
9060 (kFullWakeReasonNone != fullWakeReason) ||
9061 (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
9062 return;
9063 }
9064
9065 // Will clear reason upon exit from full wake
9066 fullWakeReason = reason;
9067
9068 _desiredCapability |= (kIOPMSystemCapabilityGraphics |
9069 kIOPMSystemCapabilityAudio);
9070
9071 if ((kSystemTransitionWake == _systemTransitionType) &&
9072 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
9073 !darkWakePowerClamped) {
9074 // Promote to full wake while waking up to dark wake due to tickle.
9075 // PM will hold off notifying the graphics subsystem about system wake
9076 // as late as possible, so if a HID tickle does arrive, graphics can
9077 // power up from this same wake transition. Otherwise, the latency to
9078 // power up graphics on the following transition can be huge on certain
9079 // systems. However, once any power clamping has taken effect, it is
9080 // too late to promote the current dark wake transition to a full wake.
9081 _pendingCapability |= (kIOPMSystemCapabilityGraphics |
9082 kIOPMSystemCapabilityAudio);
9083
9084 // Tell the PCI parent of audio and graphics drivers to stop
9085 // delaying the child notifications. Same for root domain.
9086 pciRoot = pciHostBridgeDriver.get();
9087 willEnterFullWake();
9088 promotion = true;
9089 }
9090
9091 // Unsafe to cancel once graphics was powered.
9092 // If system woke from dark wake, the return to sleep can
9093 // be cancelled. "awake -> dark -> sleep" transition
9094 // can be cancelled also, during the "dark -> sleep" phase
9095 // *prior* to driver power down.
9096 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
9097 _pendingCapability == 0) {
9098 options |= kIOPMSyncCancelPowerDown;
9099 }
9100
9101 synchronizePowerTree(options, pciRoot);
9102
9103 if (kFullWakeReasonLocalUser == fullWakeReason) {
9104 // IOGraphics doesn't light the display even though graphics is
9105 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
9106 // So, do an explicit activity tickle
9107 if (wrangler) {
9108 wrangler->activityTickle(0, 0);
9109 }
9110 }
9111
9112 // Log a timestamp for the initial full wake request.
9113 // System may not always honor this full wake request.
9114 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9115 AbsoluteTime now;
9116 uint64_t nsec;
9117
9118 clock_get_uptime(&now);
9119 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9120 absolutetime_to_nanoseconds(now, &nsec);
9121 MSG("full wake %s (reason %u) %u ms\n",
9122 promotion ? "promotion" : "request",
9123 fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9124 }
9125 }
9126
9127 //******************************************************************************
9128 // willEnterFullWake
9129 //
9130 // System will enter full wake from sleep, from dark wake, or from dark
9131 // wake promotion. This function aggregate things that are in common to
9132 // all three full wake transitions.
9133 //
9134 // Assumptions: fullWakeReason was updated
9135 //******************************************************************************
9136
9137 void
9138 IOPMrootDomain::willEnterFullWake( void )
9139 {
9140 hibernateRetry = false;
9141 sleepToStandby = false;
9142 standbyNixed = false;
9143 resetTimers = false;
9144 sleepTimerMaintenance = false;
9145
9146 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9147
9148 _systemMessageClientMask = kSystemMessageClientPowerd |
9149 kSystemMessageClientLegacyApp;
9150
9151 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9152 // First time to attain full wake capability since the last wake
9153 _systemMessageClientMask |= kSystemMessageClientKernel;
9154
9155 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9156 setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9157 (kFullWakeReasonLocalUser == fullWakeReason) ?
9158 kOSBooleanTrue : kOSBooleanFalse);
9159 }
9160 #if HIBERNATION
9161 IOHibernateSetWakeCapabilities(_pendingCapability);
9162 #endif
9163
9164 IOService::setAdvisoryTickleEnable( true );
9165 tellClients(kIOMessageSystemWillPowerOn);
9166 preventTransitionToUserActive(false);
9167 }
9168
9169 //******************************************************************************
9170 // fullWakeDelayedWork
9171 //
9172 // System has already entered full wake. Invoked by a delayed thread call.
9173 //******************************************************************************
9174
9175 void
9176 IOPMrootDomain::fullWakeDelayedWork( void )
9177 {
9178 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9179 if (!gIOPMWorkLoop->inGate()) {
9180 gIOPMWorkLoop->runAction(
9181 OSMemberFunctionCast(IOWorkLoop::Action, this,
9182 &IOPMrootDomain::fullWakeDelayedWork), this);
9183 return;
9184 }
9185
9186 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9187 _currentCapability, _pendingCapability, _highestCapability,
9188 clamshellDisabled, clamshellSleepDisableMask);
9189
9190 if (clamshellExists &&
9191 CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9192 !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9193 if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9194 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9195 } else {
9196 // Not the initial full wake after waking from sleep.
9197 // Evaluate the clamshell for rdar://problem/9157444.
9198 receivePowerNotification(kLocalEvalClamshellCommand);
9199 }
9200 }
9201 #endif
9202 }
9203
9204 //******************************************************************************
9205 // evaluateAssertions
9206 //
9207 //******************************************************************************
9208
9209 // Bitmask of all kernel assertions that prevent system idle sleep.
9210 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9211 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9212 (kIOPMDriverAssertionReservedBit7 | \
9213 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9214
9215 void
9216 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9217 {
9218 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9219
9220 messageClients(kIOPMMessageDriverAssertionsChanged);
9221
9222 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9223 if (wrangler) {
9224 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9225
9226 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9227 wrangler->setIgnoreIdleTimer( value );
9228 }
9229 }
9230
9231 if (changedBits & kIOPMDriverAssertionCPUBit) {
9232 if (_aotNow) {
9233 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9234 }
9235 evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9236 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9237 AbsoluteTime now;
9238 clock_usec_t microsecs;
9239 clock_get_uptime(&now);
9240 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9241 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
9242 if (assertOnWakeReport) {
9243 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9244 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9245 }
9246 }
9247 }
9248
9249 if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9250 if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9251 if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9252 DLOG("PreventIdleSleep driver assertion raised\n");
9253 bool ok = updatePreventIdleSleepList(this, true);
9254 if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9255 // Cancel idle sleep if there is one in progress
9256 cancelIdlePowerDown(this);
9257 }
9258 }
9259 } else {
9260 DLOG("PreventIdleSleep driver assertion dropped\n");
9261 updatePreventIdleSleepList(this, false);
9262 }
9263 }
9264 }
9265
9266 // MARK: -
9267 // MARK: Statistics
9268
9269 //******************************************************************************
9270 // pmStats
9271 //
9272 //******************************************************************************
9273
9274 void
9275 IOPMrootDomain::pmStatsRecordEvent(
9276 int eventIndex,
9277 AbsoluteTime timestamp)
9278 {
9279 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9280 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9281 uint64_t delta;
9282 uint64_t nsec;
9283 OSSharedPtr<OSData> publishPMStats;
9284
9285 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9286
9287 absolutetime_to_nanoseconds(timestamp, &nsec);
9288
9289 switch (eventIndex) {
9290 case kIOPMStatsHibernateImageWrite:
9291 if (starting) {
9292 gPMStats.hibWrite.start = nsec;
9293 } else if (stopping) {
9294 gPMStats.hibWrite.stop = nsec;
9295 }
9296
9297 if (stopping) {
9298 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9299 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9300 }
9301 break;
9302 case kIOPMStatsHibernateImageRead:
9303 if (starting) {
9304 gPMStats.hibRead.start = nsec;
9305 } else if (stopping) {
9306 gPMStats.hibRead.stop = nsec;
9307 }
9308
9309 if (stopping) {
9310 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9311 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9312
9313 publishPMStats = OSData::withValue(gPMStats);
9314 setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9315 bzero(&gPMStats, sizeof(gPMStats));
9316 }
9317 break;
9318 }
9319 }
9320
9321 /*
9322 * Appends a record of the application response to
9323 * IOPMrootDomain::pmStatsAppResponses
9324 */
9325 void
9326 IOPMrootDomain::pmStatsRecordApplicationResponse(
9327 const OSSymbol *response,
9328 const char *name,
9329 int messageType,
9330 uint32_t delay_ms,
9331 uint64_t id,
9332 OSObject *object,
9333 IOPMPowerStateIndex powerState,
9334 bool async)
9335 {
9336 OSSharedPtr<OSDictionary> responseDescription;
9337 OSSharedPtr<OSNumber> delayNum;
9338 OSSharedPtr<OSNumber> powerCaps;
9339 OSSharedPtr<OSNumber> pidNum;
9340 OSSharedPtr<OSNumber> msgNum;
9341 OSSharedPtr<const OSSymbol> appname;
9342 OSSharedPtr<const OSSymbol> sleep;
9343 OSSharedPtr<const OSSymbol> wake;
9344 IOPMServiceInterestNotifier *notify = NULL;
9345
9346 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9347 if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9348 notify->ackTimeoutCnt++;
9349 } else {
9350 notify->ackTimeoutCnt = 0;
9351 }
9352 }
9353
9354 if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9355 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9356 return;
9357 }
9358
9359
9360 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9361 kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9362 } else if (notify) {
9363 // User space app or kernel capability client
9364 if (id) {
9365 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9366 } else {
9367 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9368 }
9369 notify->msgType = 0;
9370 }
9371
9372 responseDescription = OSDictionary::withCapacity(5);
9373 if (responseDescription) {
9374 if (response) {
9375 responseDescription->setObject(_statsResponseTypeKey.get(), response);
9376 }
9377
9378 msgNum = OSNumber::withNumber(messageType, 32);
9379 if (msgNum) {
9380 responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9381 }
9382
9383 if (!name && notify && notify->identifier) {
9384 name = notify->identifier->getCStringNoCopy();
9385 }
9386
9387 if (name && (strlen(name) > 0)) {
9388 appname = OSSymbol::withCString(name);
9389 if (appname) {
9390 responseDescription->setObject(_statsNameKey.get(), appname.get());
9391 }
9392 }
9393
9394 if (!id && notify) {
9395 id = notify->uuid0;
9396 }
9397 pidNum = OSNumber::withNumber(id, 64);
9398 if (pidNum) {
9399 responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9400 }
9401
9402 delayNum = OSNumber::withNumber(delay_ms, 32);
9403 if (delayNum) {
9404 responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9405 }
9406
9407 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9408 powerCaps = OSNumber::withNumber(powerState, 32);
9409
9410 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9411 static const char * driverCallTypes[] = {
9412 [kDriverCallInformPreChange] = "powerStateWillChangeTo",
9413 [kDriverCallInformPostChange] = "powerStateDidChangeTo",
9414 [kDriverCallSetPowerState] = "setPowerState"
9415 };
9416
9417 if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9418 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9419 name, id, driverCallTypes[messageType], (uint32_t) powerState,
9420 async ? "async " : "", delay_ms);
9421 }
9422 #endif
9423 } else {
9424 powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9425 }
9426 if (powerCaps) {
9427 responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9428 }
9429
9430 sleep = OSSymbol::withCString("Sleep");
9431 wake = OSSymbol::withCString("Wake");
9432 if (_systemTransitionType == kSystemTransitionSleep) {
9433 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9434 } else if (_systemTransitionType == kSystemTransitionWake) {
9435 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9436 } else if (_systemTransitionType == kSystemTransitionCapability) {
9437 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9438 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9439 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9440 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9441 }
9442 }
9443
9444 IOLockLock(pmStatsLock);
9445 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9446 pmStatsAppResponses->setObject(responseDescription.get());
9447 }
9448 IOLockUnlock(pmStatsLock);
9449 }
9450
9451 return;
9452 }
9453
9454 // MARK: -
9455 // MARK: PMTraceWorker
9456
9457 //******************************************************************************
9458 // TracePoint support
9459 //
9460 //******************************************************************************
9461
9462 #define kIOPMRegisterNVRAMTracePointHandlerKey \
9463 "IOPMRegisterNVRAMTracePointHandler"
9464
9465 IOReturn
9466 IOPMrootDomain::callPlatformFunction(
9467 const OSSymbol * functionName,
9468 bool waitForFunction,
9469 void * param1, void * param2,
9470 void * param3, void * param4 )
9471 {
9472 if (pmTracer && functionName &&
9473 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9474 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9475 uint32_t tracePointPhases, tracePointPCI;
9476 uint64_t statusCode;
9477
9478 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9479 pmTracer->tracePointTarget = (void *) param2;
9480 tracePointPCI = (uint32_t)(uintptr_t) param3;
9481 tracePointPhases = (uint32_t)(uintptr_t) param4;
9482 if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9483 OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9484 if (node) {
9485 OSSharedPtr<OSObject> bootRomFailureProp;
9486 bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9487 OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9488 uint32_t bootFailureCode;
9489 if (data && data->getLength() == sizeof(bootFailureCode)) {
9490 // Failure code from EFI/BootRom is a four byte structure
9491 memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9492 tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9493 }
9494 }
9495 }
9496 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9497 if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9498 MSG("Sleep failure code 0x%08x 0x%08x\n",
9499 tracePointPCI, tracePointPhases);
9500 }
9501 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9502 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9503
9504 return kIOReturnSuccess;
9505 }
9506 #if HIBERNATION
9507 else if (functionName &&
9508 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9509 if (gSleepPolicyHandler) {
9510 return kIOReturnExclusiveAccess;
9511 }
9512 if (!param1) {
9513 return kIOReturnBadArgument;
9514 }
9515 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9516 gSleepPolicyTarget = (void *) param2;
9517 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9518 return kIOReturnSuccess;
9519 }
9520 #endif
9521
9522 return super::callPlatformFunction(
9523 functionName, waitForFunction, param1, param2, param3, param4);
9524 }
9525
9526 void
9527 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9528 uintptr_t param1, uintptr_t param2, uintptr_t param3)
9529 {
9530 uint32_t code = IODBG_POWER(event);
9531 uint64_t regId = id;
9532 if (regId == 0) {
9533 regId = getRegistryEntryID();
9534 }
9535 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9536 }
9537
9538 void
9539 IOPMrootDomain::tracePoint( uint8_t point )
9540 {
9541 if (systemBooting) {
9542 return;
9543 }
9544
9545 if (kIOPMTracePointWakeCapabilityClients == point) {
9546 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9547 }
9548
9549 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9550 pmTracer->tracePoint(point);
9551 }
9552
9553 static void
9554 kext_log_putc(char c)
9555 {
9556 if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9557 return;
9558 }
9559 if (c == '(' || c == '[' || c == ' ') {
9560 c = 0;
9561 gKextNameEnd = true;
9562 }
9563
9564 gKextNameBuf[gKextNamePos++] = c;
9565 }
9566
9567 static int
9568 kext_log(const char *fmt, ...)
9569 {
9570 va_list listp;
9571
9572 va_start(listp, fmt);
9573 _doprnt(fmt, &listp, &kext_log_putc, 16);
9574 va_end(listp);
9575
9576 return 0;
9577 }
9578
9579 static OSPtr<const OSSymbol>
9580 copyKextIdentifierWithAddress(vm_address_t address)
9581 {
9582 OSSharedPtr<const OSSymbol> identifer;
9583
9584 IOLockLock(gHaltLogLock);
9585
9586 gKextNameEnd = false;
9587 gKextNamePos = 0;
9588 gKextNameBuf[0] = 0;
9589
9590 OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9591 gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9592 identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9593
9594 IOLockUnlock(gHaltLogLock);
9595
9596 return identifer;
9597 }
9598
9599 // Caller serialized using PM workloop
9600 const char *
9601 IOPMrootDomain::getNotificationClientName(OSObject *object)
9602 {
9603 IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9604 const char *clientName = "UNKNOWN";
9605
9606 if (!notifier->clientName) {
9607 // Check for user client
9608 if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9609 OSNumber *clientID = NULL;
9610 messageClient(kIOMessageCopyClientID, object, &clientID);
9611 if (clientID) {
9612 OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9613 if (string) {
9614 notifier->clientName = OSSymbol::withString(string.get());
9615 }
9616 clientID->release();
9617 }
9618 } else if (notifier->identifier) {
9619 notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9620 }
9621 }
9622
9623 if (notifier->clientName) {
9624 clientName = notifier->clientName->getCStringNoCopy();
9625 }
9626
9627 return clientName;
9628 }
9629
9630 void
9631 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9632 {
9633 IOPMServiceInterestNotifier *notifier;
9634
9635 if (systemBooting) {
9636 return;
9637 }
9638 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9639 if (!notifier) {
9640 return;
9641 }
9642
9643 if (start) {
9644 pmTracer->traceDetail(notifier->uuid0 >> 32);
9645 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9646 (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9647
9648 // Update notifier state used for response/ack logging
9649 notifier->msgIndex = msgIndex;
9650 notifier->msgAbsTime = timestamp;
9651
9652 if (msgIndex != UINT_MAX) {
9653 DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9654 } else {
9655 DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9656 }
9657
9658 assert(notifierObject == NULL);
9659 notifierThread = current_thread();
9660 notifierObject.reset(notifier, OSRetain);
9661 } else {
9662 uint64_t nsec;
9663 uint32_t delayMS;
9664
9665 SUB_ABSOLUTETIME(×tamp, ¬ifier->msgAbsTime);
9666 absolutetime_to_nanoseconds(timestamp, &nsec);
9667 delayMS = (uint32_t)(nsec / 1000000ULL);
9668 if (delayMS > notifier->maxMsgDelayMS) {
9669 notifier->maxMsgDelayMS = delayMS;
9670 }
9671
9672 assert(notifierObject == notifier);
9673 notifierObject.reset();
9674 notifierThread = NULL;
9675 }
9676 }
9677
9678 void
9679 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9680 {
9681 if (systemBooting) {
9682 return;
9683 }
9684 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9685 if (!notifier) {
9686 return;
9687 }
9688
9689 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9690 (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9691
9692 DLOG("%s[%u] ack from %s took %d ms\n",
9693 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9694 if (delay_ms > notifier->maxAckDelayMS) {
9695 notifier->maxAckDelayMS = delay_ms;
9696 }
9697 }
9698
9699 void
9700 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9701 {
9702 if (systemBooting) {
9703 return;
9704 }
9705 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9706 if (!notifier) {
9707 return;
9708 }
9709
9710 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9711 (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9712
9713 if (ack_time_us == 0) {
9714 // Client work is done and ack will not be forthcoming
9715 DLOG("%s[%u] response from %s took %d ms\n",
9716 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9717 } else {
9718 // Client needs more time and it must ack within ack_time_us
9719 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9720 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9721 }
9722 }
9723
9724 void
9725 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9726 {
9727 if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9728 return;
9729 }
9730 if (systemBooting) {
9731 return;
9732 }
9733 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9734 if (!notifier) {
9735 return;
9736 }
9737
9738 DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9739 }
9740
9741 void
9742 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9743 {
9744 if (!systemBooting) {
9745 uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
9746 pmTracer->traceDetail( detail );
9747 kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
9748 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
9749 }
9750 }
9751
9752 void
9753 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9754 {
9755 size_t reportSize;
9756 void **report = NULL;
9757 uint32_t bktCnt;
9758 uint32_t bktSize;
9759 uint32_t *clientCnt;
9760
9761 ASSERT_GATED();
9762
9763 report = NULL;
9764 if (channel_id == kAssertDelayChID) {
9765 report = &assertOnWakeReport;
9766 bktCnt = kAssertDelayBcktCnt;
9767 bktSize = kAssertDelayBcktSize;
9768 clientCnt = &assertOnWakeClientCnt;
9769 } else if (channel_id == kSleepDelaysChID) {
9770 report = &sleepDelaysReport;
9771 bktCnt = kSleepDelaysBcktCnt;
9772 bktSize = kSleepDelaysBcktSize;
9773 clientCnt = &sleepDelaysClientCnt;
9774 } else {
9775 assert(false);
9776 return;
9777 }
9778
9779 switch (action) {
9780 case kIOReportEnable:
9781
9782 if (*report) {
9783 (*clientCnt)++;
9784 break;
9785 }
9786
9787 reportSize = HISTREPORT_BUFSIZE(bktCnt);
9788 *report = IOMallocZeroData(reportSize);
9789 if (*report == NULL) {
9790 break;
9791 }
9792 HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9793 getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9794
9795 if (channel_id == kAssertDelayChID) {
9796 assertOnWakeSecs = 0;
9797 }
9798
9799 break;
9800
9801 case kIOReportDisable:
9802 if (*clientCnt == 0) {
9803 break;
9804 }
9805 if (*clientCnt == 1) {
9806 IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
9807 *report = NULL;
9808 }
9809 (*clientCnt)--;
9810
9811 if (channel_id == kAssertDelayChID) {
9812 assertOnWakeSecs = -1; // Invalid value to prevent updates
9813 }
9814 break;
9815
9816 case kIOReportGetDimensions:
9817 if (*report) {
9818 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9819 }
9820 break;
9821 }
9822
9823 return;
9824 }
9825
9826 IOReturn
9827 IOPMrootDomain::configureReport(IOReportChannelList *channelList,
9828 IOReportConfigureAction action,
9829 void *result,
9830 void *destination)
9831 {
9832 unsigned cnt;
9833 uint64_t configAction = (uint64_t)action;
9834
9835 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9836 if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
9837 (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
9838 (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
9839 if (action != kIOReportGetDimensions) {
9840 continue;
9841 }
9842 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
9843 } else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
9844 (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
9845 gIOPMWorkLoop->runAction(
9846 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
9847 (OSObject *)this, (void *)channelList->channels[cnt].channel_id,
9848 (void *)configAction, (void *)result);
9849 }
9850 }
9851
9852 return super::configureReport(channelList, action, result, destination);
9853 }
9854
9855 IOReturn
9856 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9857 {
9858 uint32_t size2cpy;
9859 void *data2cpy;
9860 void **report;
9861
9862 ASSERT_GATED();
9863
9864 report = NULL;
9865 if (ch_id == kAssertDelayChID) {
9866 report = &assertOnWakeReport;
9867 } else if (ch_id == kSleepDelaysChID) {
9868 report = &sleepDelaysReport;
9869 } else {
9870 assert(false);
9871 return kIOReturnBadArgument;
9872 }
9873
9874 if (*report == NULL) {
9875 return kIOReturnNotOpen;
9876 }
9877
9878 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9879 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9880 return kIOReturnOverrun;
9881 }
9882
9883 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9884 dest->appendBytes(data2cpy, size2cpy);
9885
9886 return kIOReturnSuccess;
9887 }
9888
9889 IOReturn
9890 IOPMrootDomain::updateReport(IOReportChannelList *channelList,
9891 IOReportUpdateAction action,
9892 void *result,
9893 void *destination)
9894 {
9895 uint32_t size2cpy;
9896 void *data2cpy;
9897 uint8_t buf[SIMPLEREPORT_BUFSIZE];
9898 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9899 unsigned cnt;
9900 uint64_t ch_id;
9901
9902 if (action != kIOReportCopyChannelData) {
9903 goto exit;
9904 }
9905
9906 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9907 ch_id = channelList->channels[cnt].channel_id;
9908
9909 if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
9910 gIOPMWorkLoop->runAction(
9911 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
9912 (OSObject *)this, (void *)ch_id,
9913 (void *)result, (void *)dest);
9914 continue;
9915 } else if ((ch_id == kSleepCntChID) ||
9916 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9917 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9918 } else {
9919 continue;
9920 }
9921
9922 if (ch_id == kSleepCntChID) {
9923 SIMPLEREPORT_SETVALUE(buf, sleepCnt);
9924 } else if (ch_id == kDarkWkCntChID) {
9925 SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
9926 } else if (ch_id == kUserWkCntChID) {
9927 SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
9928 }
9929
9930 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9931 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9932 dest->appendBytes(data2cpy, size2cpy);
9933 }
9934
9935 exit:
9936 return super::updateReport(channelList, action, result, destination);
9937 }
9938
9939
9940 //******************************************************************************
9941 // PMTraceWorker Class
9942 //
9943 //******************************************************************************
9944
9945 #undef super
9946 #define super OSObject
9947 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9948
9949 #define kPMBestGuessPCIDevicesCount 25
9950 #define kPMMaxRTCBitfieldSize 32
9951
9952 OSPtr<PMTraceWorker>
9953 PMTraceWorker::tracer(IOPMrootDomain * owner)
9954 {
9955 OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9956 if (!me || !me->init()) {
9957 return NULL;
9958 }
9959
9960 DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9961
9962 // Note that we cannot instantiate the PCI device -> bit mappings here, since
9963 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
9964 // this dictionary lazily.
9965 me->owner = owner;
9966 me->pciDeviceBitMappings = NULL;
9967 me->pmTraceWorkerLock = IOLockAlloc();
9968 me->tracePhase = kIOPMTracePointSystemUp;
9969 me->traceData32 = 0;
9970 me->loginWindowData = 0;
9971 me->coreDisplayData = 0;
9972 me->coreGraphicsData = 0;
9973 return me;
9974 }
9975
9976 void
9977 PMTraceWorker::RTC_TRACE(void)
9978 {
9979 if (tracePointHandler && tracePointTarget) {
9980 uint32_t wordA;
9981
9982 IOLockLock(pmTraceWorkerLock);
9983 wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9984 (coreGraphicsData << 8) | tracePhase;
9985 IOLockUnlock(pmTraceWorkerLock);
9986
9987 tracePointHandler( tracePointTarget, traceData32, wordA );
9988 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
9989 }
9990 #if DEVELOPMENT || DEBUG
9991 if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
9992 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
9993 IOLock *l = IOLockAlloc();
9994 IOLockLock(l);
9995 IOLockLock(l);
9996 }
9997 #endif /* DEVELOPMENT || DEBUG */
9998 }
9999
10000 int
10001 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
10002 {
10003 OSSharedPtr<const OSSymbol> deviceName;
10004 int index = -1;
10005
10006 IOLockLock(pmTraceWorkerLock);
10007
10008 if (!pciDeviceBitMappings) {
10009 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
10010 if (!pciDeviceBitMappings) {
10011 goto exit;
10012 }
10013 }
10014
10015 // Check for bitmask overflow.
10016 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
10017 goto exit;
10018 }
10019
10020 if ((deviceName = pciDevice->copyName()) &&
10021 (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
10022 pciDeviceBitMappings->setObject(deviceName.get())) {
10023 index = pciDeviceBitMappings->getCount() - 1;
10024 _LOG("PMTrace PCI array: set object %s => %d\n",
10025 deviceName->getCStringNoCopy(), index);
10026 }
10027
10028 if (!addedToRegistry && (index >= 0)) {
10029 addedToRegistry = owner->setProperty("PCITopLevel", this);
10030 }
10031
10032 exit:
10033 IOLockUnlock(pmTraceWorkerLock);
10034 return index;
10035 }
10036
10037 bool
10038 PMTraceWorker::serialize(OSSerialize *s) const
10039 {
10040 bool ok = false;
10041 if (pciDeviceBitMappings) {
10042 IOLockLock(pmTraceWorkerLock);
10043 ok = pciDeviceBitMappings->serialize(s);
10044 IOLockUnlock(pmTraceWorkerLock);
10045 }
10046 return ok;
10047 }
10048
10049 void
10050 PMTraceWorker::tracePoint(uint8_t phase)
10051 {
10052 // clear trace detail when phase begins
10053 if (tracePhase != phase) {
10054 traceData32 = 0;
10055 }
10056
10057 tracePhase = phase;
10058
10059 DLOG("trace point 0x%02x\n", tracePhase);
10060 RTC_TRACE();
10061 }
10062
10063 void
10064 PMTraceWorker::traceDetail(uint32_t detail)
10065 {
10066 if (detail == traceData32) {
10067 return;
10068 }
10069 traceData32 = detail;
10070 RTC_TRACE();
10071 }
10072
10073 void
10074 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
10075 {
10076 switch (component) {
10077 case kIOPMLoginWindowProgress:
10078 loginWindowData = data & kIOPMLoginWindowProgressMask;
10079 break;
10080 case kIOPMCoreDisplayProgress:
10081 coreDisplayData = data & kIOPMCoreDisplayProgressMask;
10082 break;
10083 case kIOPMCoreGraphicsProgress:
10084 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
10085 break;
10086 default:
10087 return;
10088 }
10089
10090 DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
10091 RTC_TRACE();
10092 }
10093
10094 void
10095 PMTraceWorker::tracePCIPowerChange(
10096 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
10097 {
10098 uint32_t bitMask;
10099 uint32_t expectedFlag;
10100
10101 // Ignore PCI changes outside of system sleep/wake.
10102 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
10103 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
10104 return;
10105 }
10106
10107 // Only record the WillChange transition when going to sleep,
10108 // and the DidChange on the way up.
10109 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
10110 expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
10111 kIOPMDomainWillChange : kIOPMDomainDidChange;
10112 if (changeFlags != expectedFlag) {
10113 return;
10114 }
10115
10116 // Mark this device off in our bitfield
10117 if (bitNum < kPMMaxRTCBitfieldSize) {
10118 bitMask = (1 << bitNum);
10119
10120 if (kPowerChangeStart == type) {
10121 traceData32 |= bitMask;
10122 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
10123 service->getName(), bitNum, bitMask, traceData32);
10124 owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10125 } else {
10126 traceData32 &= ~bitMask;
10127 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10128 service->getName(), bitNum, bitMask, traceData32);
10129 owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10130 }
10131
10132 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10133 RTC_TRACE();
10134 }
10135 }
10136
10137 uint64_t
10138 PMTraceWorker::getPMStatusCode()
10139 {
10140 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10141 }
10142
10143 uint8_t
10144 PMTraceWorker::getTracePhase()
10145 {
10146 return tracePhase;
10147 }
10148
10149 uint32_t
10150 PMTraceWorker::getTraceData()
10151 {
10152 return traceData32;
10153 }
10154
10155 // MARK: -
10156 // MARK: PMHaltWorker
10157
10158 //******************************************************************************
10159 // PMHaltWorker Class
10160 //
10161 //******************************************************************************
10162
10163 PMHaltWorker *
10164 PMHaltWorker::worker( void )
10165 {
10166 PMHaltWorker * me;
10167 IOThread thread;
10168
10169 do {
10170 me = OSTypeAlloc( PMHaltWorker );
10171 if (!me || !me->init()) {
10172 break;
10173 }
10174
10175 me->lock = IOLockAlloc();
10176 if (!me->lock) {
10177 break;
10178 }
10179
10180 DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10181 me->retain(); // thread holds extra retain
10182 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10183 me->release();
10184 break;
10185 }
10186 thread_deallocate(thread);
10187 return me;
10188 } while (false);
10189
10190 if (me) {
10191 me->release();
10192 }
10193 return NULL;
10194 }
10195
10196 void
10197 PMHaltWorker::free( void )
10198 {
10199 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10200 if (lock) {
10201 IOLockFree(lock);
10202 lock = NULL;
10203 }
10204 return OSObject::free();
10205 }
10206
10207 void
10208 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10209 {
10210 PMHaltWorker * me = (PMHaltWorker *) arg;
10211
10212 IOLockLock( gPMHaltLock );
10213 gPMHaltBusyCount++;
10214 me->depth = gPMHaltDepth;
10215 IOLockUnlock( gPMHaltLock );
10216
10217 while (me->depth >= 0) {
10218 PMHaltWorker::work( me );
10219
10220 IOLockLock( gPMHaltLock );
10221 if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10222 // This is the last thread to finish work on this level,
10223 // inform everyone to start working on next lower level.
10224 gPMHaltDepth--;
10225 me->depth = gPMHaltDepth;
10226 gPMHaltIdleCount = 0;
10227 thread_wakeup((event_t) &gPMHaltIdleCount);
10228 } else {
10229 // One or more threads are still working on this level,
10230 // this thread must wait.
10231 me->depth = gPMHaltDepth - 1;
10232 do {
10233 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10234 } while (me->depth != gPMHaltDepth);
10235 }
10236 IOLockUnlock( gPMHaltLock );
10237 }
10238
10239 // No more work to do, terminate thread
10240 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10241 thread_wakeup( &gPMHaltDepth );
10242 me->release();
10243 }
10244
10245 void
10246 PMHaltWorker::work( PMHaltWorker * me )
10247 {
10248 OSSharedPtr<IOService> service;
10249 OSSet * inner;
10250 AbsoluteTime startTime, elapsedTime;
10251 UInt32 deltaTime;
10252 bool timeout;
10253
10254 while (true) {
10255 timeout = false;
10256
10257 // Claim an unit of work from the shared pool
10258 IOLockLock( gPMHaltLock );
10259 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10260 if (inner) {
10261 service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10262 if (service) {
10263 inner->removeObject(service.get());
10264 }
10265 }
10266 IOLockUnlock( gPMHaltLock );
10267 if (!service) {
10268 break; // no more work at this depth
10269 }
10270 clock_get_uptime(&startTime);
10271
10272 if (!service->isInactive() &&
10273 service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10274 IOLockLock(me->lock);
10275 me->startTime = startTime;
10276 me->service = service.get();
10277 me->timeout = false;
10278 IOLockUnlock(me->lock);
10279
10280 service->systemWillShutdown( gPMHaltMessageType);
10281
10282 // Wait for driver acknowledgement
10283 IOLockLock(me->lock);
10284 while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10285 IOLockSleep(me->lock, me, THREAD_UNINT);
10286 }
10287 me->service = NULL;
10288 timeout = me->timeout;
10289 IOLockUnlock(me->lock);
10290 }
10291
10292 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10293 if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10294 LOG("%s driver %s (0x%llx) took %u ms\n",
10295 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10296 "PowerOff" : "Restart",
10297 service->getName(), service->getRegistryEntryID(),
10298 (uint32_t) deltaTime );
10299 halt_log_enter("PowerOff/Restart handler completed",
10300 OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10301 elapsedTime);
10302 }
10303
10304 me->visits++;
10305 }
10306 }
10307
10308 void
10309 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10310 {
10311 UInt64 nano;
10312 AbsoluteTime startTime;
10313 AbsoluteTime endTime;
10314
10315 endTime = *now;
10316
10317 IOLockLock(me->lock);
10318 if (me->service && !me->timeout) {
10319 startTime = me->startTime;
10320 nano = 0;
10321 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10322 SUB_ABSOLUTETIME(&endTime, &startTime);
10323 absolutetime_to_nanoseconds(endTime, &nano);
10324 }
10325 if (nano > 3000000000ULL) {
10326 me->timeout = true;
10327
10328 halt_log_enter("PowerOff/Restart still waiting on handler",
10329 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10330 endTime);
10331 MSG("%s still waiting on %s\n",
10332 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart",
10333 me->service->getName());
10334 }
10335 }
10336 IOLockUnlock(me->lock);
10337 }
10338
10339 //******************************************************************************
10340 // acknowledgeSystemWillShutdown
10341 //
10342 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10343 //******************************************************************************
10344
10345 void
10346 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10347 {
10348 PMHaltWorker * worker;
10349 OSSharedPtr<OSObject> prop;
10350
10351 if (!from) {
10352 return;
10353 }
10354
10355 //DLOG("%s acknowledged\n", from->getName());
10356 prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10357 if (prop) {
10358 worker = (PMHaltWorker *) prop.get();
10359 IOLockLock(worker->lock);
10360 from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10361 thread_wakeup((event_t) worker);
10362 IOLockUnlock(worker->lock);
10363 } else {
10364 DLOG("%s acknowledged without worker property\n",
10365 from->getName());
10366 }
10367 }
10368
10369
10370 //******************************************************************************
10371 // notifySystemShutdown
10372 //
10373 // Notify all objects in PM tree that system will shutdown or restart
10374 //******************************************************************************
10375
10376 static void
10377 notifySystemShutdown( IOService * root, uint32_t messageType )
10378 {
10379 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10380 OSSharedPtr<IORegistryIterator> iter;
10381 IORegistryEntry * entry;
10382 IOService * node;
10383 OSSet * inner;
10384 OSSharedPtr<OSSet> newInner;
10385 PMHaltWorker * workers[kPMHaltMaxWorkers];
10386 AbsoluteTime deadline;
10387 unsigned int totalNodes = 0;
10388 unsigned int depth;
10389 unsigned int rootDepth;
10390 unsigned int numWorkers;
10391 unsigned int count;
10392 int waitResult;
10393 void * baseFunc;
10394 bool ok;
10395
10396 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10397
10398 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10399
10400 // Iterate the entire PM tree starting from root
10401
10402 rootDepth = root->getDepth( gIOPowerPlane );
10403 if (!rootDepth) {
10404 goto done;
10405 }
10406
10407 // debug - for repeated test runs
10408 while (PMHaltWorker::metaClass->getInstanceCount()) {
10409 IOSleep(1);
10410 }
10411
10412 if (!gPMHaltArray) {
10413 gPMHaltArray = OSArray::withCapacity(40);
10414 if (!gPMHaltArray) {
10415 goto done;
10416 }
10417 } else { // debug
10418 gPMHaltArray->flushCollection();
10419 }
10420
10421 if (!gPMHaltLock) {
10422 gPMHaltLock = IOLockAlloc();
10423 if (!gPMHaltLock) {
10424 goto done;
10425 }
10426 }
10427
10428 if (!gPMHaltClientAcknowledgeKey) {
10429 gPMHaltClientAcknowledgeKey =
10430 OSSymbol::withCStringNoCopy("PMShutdown");
10431 if (!gPMHaltClientAcknowledgeKey) {
10432 goto done;
10433 }
10434 }
10435
10436 gPMHaltMessageType = messageType;
10437
10438 // Depth-first walk of PM plane
10439
10440 iter = IORegistryIterator::iterateOver(
10441 root, gIOPowerPlane, kIORegistryIterateRecursively);
10442
10443 if (iter) {
10444 while ((entry = iter->getNextObject())) {
10445 node = OSDynamicCast(IOService, entry);
10446 if (!node) {
10447 continue;
10448 }
10449
10450 if (baseFunc ==
10451 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10452 continue;
10453 }
10454
10455 depth = node->getDepth( gIOPowerPlane );
10456 if (depth <= rootDepth) {
10457 continue;
10458 }
10459
10460 ok = false;
10461
10462 // adjust to zero based depth
10463 depth -= (rootDepth + 1);
10464
10465 // gPMHaltArray is an array of containers, each container
10466 // refers to nodes with the same depth.
10467
10468 count = gPMHaltArray->getCount();
10469 while (depth >= count) {
10470 // expand array and insert placeholders
10471 gPMHaltArray->setObject(PLACEHOLDER);
10472 count++;
10473 }
10474 count = gPMHaltArray->getCount();
10475 if (depth < count) {
10476 inner = (OSSet *)gPMHaltArray->getObject(depth);
10477 if (inner == PLACEHOLDER) {
10478 newInner = OSSet::withCapacity(40);
10479 if (newInner) {
10480 gPMHaltArray->replaceObject(depth, newInner.get());
10481 inner = newInner.get();
10482 }
10483 }
10484
10485 // PM nodes that appear more than once in the tree will have
10486 // the same depth, OSSet will refuse to add the node twice.
10487 if (inner) {
10488 ok = inner->setObject(node);
10489 }
10490 }
10491 if (!ok) {
10492 DLOG("Skipped PM node %s\n", node->getName());
10493 }
10494 }
10495 }
10496
10497 // debug only
10498 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10499 count = 0;
10500 if (inner != PLACEHOLDER) {
10501 count = inner->getCount();
10502 }
10503 DLOG("Nodes at depth %u = %u\n", i, count);
10504 }
10505
10506 // strip placeholders (not all depths are populated)
10507 numWorkers = 0;
10508 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10509 if (inner == PLACEHOLDER) {
10510 gPMHaltArray->removeObject(i);
10511 continue;
10512 }
10513 count = inner->getCount();
10514 if (count > numWorkers) {
10515 numWorkers = count;
10516 }
10517 totalNodes += count;
10518 i++;
10519 }
10520
10521 if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10522 goto done;
10523 }
10524
10525 gPMHaltBusyCount = 0;
10526 gPMHaltIdleCount = 0;
10527 gPMHaltDepth = gPMHaltArray->getCount() - 1;
10528
10529 // Create multiple workers (and threads)
10530
10531 if (numWorkers > kPMHaltMaxWorkers) {
10532 numWorkers = kPMHaltMaxWorkers;
10533 }
10534
10535 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10536 totalNodes, gPMHaltArray->getCount(), numWorkers);
10537
10538 for (unsigned int i = 0; i < numWorkers; i++) {
10539 workers[i] = PMHaltWorker::worker();
10540 }
10541
10542 // Wait for workers to exhaust all available work
10543
10544 IOLockLock(gPMHaltLock);
10545 while (gPMHaltDepth >= 0) {
10546 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10547
10548 waitResult = IOLockSleepDeadline(
10549 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10550 if (THREAD_TIMED_OUT == waitResult) {
10551 AbsoluteTime now;
10552 clock_get_uptime(&now);
10553
10554 IOLockUnlock(gPMHaltLock);
10555 for (unsigned int i = 0; i < numWorkers; i++) {
10556 if (workers[i]) {
10557 PMHaltWorker::checkTimeout(workers[i], &now);
10558 }
10559 }
10560 IOLockLock(gPMHaltLock);
10561 }
10562 }
10563 IOLockUnlock(gPMHaltLock);
10564
10565 // Release all workers
10566
10567 for (unsigned int i = 0; i < numWorkers; i++) {
10568 if (workers[i]) {
10569 workers[i]->release();
10570 }
10571 // worker also retained by it's own thread
10572 }
10573
10574 done:
10575 DLOG("%s done\n", __FUNCTION__);
10576 return;
10577 }
10578
10579 // MARK: -
10580 // MARK: Kernel Assertion
10581
10582 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10583
10584 IOPMDriverAssertionID
10585 IOPMrootDomain::createPMAssertion(
10586 IOPMDriverAssertionType whichAssertionBits,
10587 IOPMDriverAssertionLevel assertionLevel,
10588 IOService *ownerService,
10589 const char *ownerDescription)
10590 {
10591 IOReturn ret;
10592 IOPMDriverAssertionID newAssertion;
10593
10594 if (!pmAssertions) {
10595 return 0;
10596 }
10597
10598 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10599
10600 if (kIOReturnSuccess == ret) {
10601 #if (DEVELOPMENT || DEBUG)
10602 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10603 const char *serviceName = (ownerService && ownerService->reserved) ? ownerService->getName() : NULL;
10604 OSReportWithBacktrace("PMRD: createPMAssertion(0x%qx) %s (%s)", newAssertion,
10605 serviceName, ownerDescription);
10606 }
10607 #endif /* (DEVELOPMENT || DEBUG) */
10608 return newAssertion;
10609 } else {
10610 return 0;
10611 }
10612 }
10613
10614 IOReturn
10615 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10616 {
10617 #if (DEVELOPMENT || DEBUG)
10618 if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10619 PMAssertStruct *details = pmAssertions->detailsForID(releaseAssertion, NULL);
10620 if (details) {
10621 const char *serviceName = (details->ownerService && details->ownerService->reserved) ?
10622 details->ownerService->getName() : NULL;
10623 const char *ownerString = details->ownerString ? details->ownerString->getCStringNoCopy() : NULL;
10624 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx) %s (%s)", releaseAssertion, serviceName, ownerString);
10625 } else {
10626 OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx)", releaseAssertion);
10627 }
10628 }
10629 #endif /* (DEVELOPMENT || DEBUG) */
10630 if (!pmAssertions) {
10631 return kIOReturnInternalError;
10632 }
10633 return pmAssertions->releaseAssertion(releaseAssertion);
10634 }
10635
10636
10637 IOReturn
10638 IOPMrootDomain::setPMAssertionLevel(
10639 IOPMDriverAssertionID assertionID,
10640 IOPMDriverAssertionLevel assertionLevel)
10641 {
10642 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10643 }
10644
10645 IOPMDriverAssertionLevel
10646 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10647 {
10648 IOPMDriverAssertionType sysLevels;
10649
10650 if (!pmAssertions || whichAssertion == 0) {
10651 return kIOPMDriverAssertionLevelOff;
10652 }
10653
10654 sysLevels = pmAssertions->getActivatedAssertions();
10655
10656 // Check that every bit set in argument 'whichAssertion' is asserted
10657 // in the aggregate bits.
10658 if ((sysLevels & whichAssertion) == whichAssertion) {
10659 return kIOPMDriverAssertionLevelOn;
10660 } else {
10661 return kIOPMDriverAssertionLevelOff;
10662 }
10663 }
10664
10665 IOReturn
10666 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10667 {
10668 if (!pmAssertions) {
10669 return kIOReturnNotFound;
10670 }
10671
10672 return pmAssertions->setUserAssertionLevels(inLevels);
10673 }
10674
10675 IOReturn
10676 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10677 {
10678 return gIOPMWorkLoop->runActionBlock(^{
10679 if (_driverKitMatchingAssertionCount != 0) {
10680 _driverKitMatchingAssertionCount++;
10681 return kIOReturnSuccess;
10682 } else {
10683 if (kSystemTransitionSleep == _systemTransitionType) {
10684 // system going to sleep
10685 return kIOReturnBusy;
10686 } else {
10687 // createPMAssertion is asynchronous.
10688 // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10689 // The assertion is used so that on release, we reevaluate all assertions
10690 _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10691 if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10692 _driverKitMatchingAssertionCount = 1;
10693 return kIOReturnSuccess;
10694 } else {
10695 return kIOReturnBusy;
10696 }
10697 }
10698 }
10699 });
10700 }
10701
10702 void
10703 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10704 {
10705 gIOPMWorkLoop->runActionBlock(^{
10706 if (_driverKitMatchingAssertionCount != 0) {
10707 _driverKitMatchingAssertionCount--;
10708 if (_driverKitMatchingAssertionCount == 0) {
10709 releasePMAssertion(_driverKitMatchingAssertion);
10710 _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10711 }
10712 } else {
10713 panic("Over-release of driverkit matching assertion");
10714 }
10715 return kIOReturnSuccess;
10716 });
10717 }
10718
10719 bool
10720 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10721 {
10722 if (pmAssertions) {
10723 pmAssertions->publishProperties();
10724 }
10725 return IOService::serializeProperties(s);
10726 }
10727
10728 OSSharedPtr<OSObject>
10729 IOPMrootDomain::copyProperty( const char * aKey) const
10730 {
10731 OSSharedPtr<OSObject> obj;
10732 obj = IOService::copyProperty(aKey);
10733
10734 if (obj) {
10735 return obj;
10736 }
10737
10738 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10739 sizeof(kIOPMSleepWakeWdogRebootKey))) {
10740 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10741 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10742 } else {
10743 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10744 }
10745 }
10746
10747 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10748 sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10749 if (swd_flags & SWD_VALID_LOGS) {
10750 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10751 } else {
10752 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10753 }
10754 }
10755
10756 /*
10757 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
10758 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10759 * issued by DisplayWrangler on darkwake.
10760 */
10761 if (!strcmp(aKey, "DesktopMode")) {
10762 if (desktopMode) {
10763 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10764 } else {
10765 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10766 }
10767 }
10768 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10769 if (displayIdleForDemandSleep) {
10770 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10771 } else {
10772 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10773 }
10774 }
10775
10776 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10777 OSSharedPtr<OSArray> array;
10778 WAKEEVENT_LOCK();
10779 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10780 OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10781 if (collection) {
10782 array = OSDynamicPtrCast<OSArray>(collection);
10783 }
10784 }
10785 WAKEEVENT_UNLOCK();
10786 return os::move(array);
10787 }
10788
10789 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10790 OSSharedPtr<OSArray> array;
10791 IOLockLock(pmStatsLock);
10792 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10793 OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10794 if (collection) {
10795 array = OSDynamicPtrCast<OSArray>(collection);
10796 }
10797 }
10798 IOLockUnlock(pmStatsLock);
10799 return os::move(array);
10800 }
10801
10802 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10803 OSArray *idleSleepList = NULL;
10804 gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10805 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10806 }
10807
10808 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10809 OSArray *systemSleepList = NULL;
10810 gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10811 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10812 }
10813
10814 if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10815 OSArray *idleSleepList = NULL;
10816 gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10817 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10818 }
10819
10820 if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10821 OSArray *systemSleepList = NULL;
10822 gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10823 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10824 }
10825 return NULL;
10826 }
10827
10828 // MARK: -
10829 // MARK: Wake Event Reporting
10830
10831 void
10832 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10833 {
10834 WAKEEVENT_LOCK();
10835 strlcpy(outBuf, gWakeReasonString, bufSize);
10836 WAKEEVENT_UNLOCK();
10837 }
10838
10839 void
10840 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10841 {
10842 WAKEEVENT_LOCK();
10843 strlcpy(outBuf, gShutdownReasonString, bufSize);
10844 WAKEEVENT_UNLOCK();
10845 }
10846
10847 //******************************************************************************
10848 // acceptSystemWakeEvents
10849 //
10850 // Private control for the acceptance of driver wake event claims.
10851 //******************************************************************************
10852
10853 void
10854 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10855 {
10856 bool logWakeReason = false;
10857
10858 WAKEEVENT_LOCK();
10859 switch (control) {
10860 case kAcceptSystemWakeEvents_Enable:
10861 assert(_acceptSystemWakeEvents == false);
10862 if (!_systemWakeEventsArray) {
10863 _systemWakeEventsArray = OSArray::withCapacity(4);
10864 }
10865 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10866 if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10867 gWakeReasonString[0] = '\0';
10868 if (_systemWakeEventsArray) {
10869 _systemWakeEventsArray->flushCollection();
10870 }
10871 }
10872
10873 // Remove stale WakeType property before system sleep
10874 removeProperty(kIOPMRootDomainWakeTypeKey);
10875 removeProperty(kIOPMRootDomainWakeReasonKey);
10876 break;
10877
10878 case kAcceptSystemWakeEvents_Disable:
10879 _acceptSystemWakeEvents = false;
10880 #if defined(XNU_TARGET_OS_OSX)
10881 logWakeReason = (gWakeReasonString[0] != '\0');
10882 #else /* !defined(XNU_TARGET_OS_OSX) */
10883 logWakeReason = gWakeReasonSysctlRegistered;
10884 #if DEVELOPMENT
10885 static int panic_allowed = -1;
10886
10887 if ((panic_allowed == -1) &&
10888 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10889 panic_allowed = 0;
10890 }
10891
10892 if (panic_allowed) {
10893 size_t i = 0;
10894 // Panic if wake reason is null or empty
10895 for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10896 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10897 break;
10898 }
10899 }
10900 if (i >= strlen(gWakeReasonString)) {
10901 panic("Wake reason is empty");
10902 }
10903 }
10904 #endif /* DEVELOPMENT */
10905 #endif /* !defined(XNU_TARGET_OS_OSX) */
10906
10907 // publish kIOPMRootDomainWakeReasonKey if not already set
10908 if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10909 setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10910 }
10911 break;
10912
10913 case kAcceptSystemWakeEvents_Reenable:
10914 assert(_acceptSystemWakeEvents == false);
10915 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10916 removeProperty(kIOPMRootDomainWakeReasonKey);
10917 break;
10918 }
10919 WAKEEVENT_UNLOCK();
10920
10921 if (logWakeReason) {
10922 MSG("system wake events: %s\n", gWakeReasonString);
10923 }
10924 }
10925
10926 //******************************************************************************
10927 // claimSystemWakeEvent
10928 //
10929 // For a driver to claim a device is the source/conduit of a system wake event.
10930 //******************************************************************************
10931
10932 void
10933 IOPMrootDomain::claimSystemWakeEvent(
10934 IOService * device,
10935 IOOptionBits flags,
10936 const char * reason,
10937 OSObject * details )
10938 {
10939 OSSharedPtr<const OSSymbol> deviceName;
10940 OSSharedPtr<OSNumber> deviceRegId;
10941 OSSharedPtr<OSNumber> claimTime;
10942 OSSharedPtr<OSData> flagsData;
10943 OSSharedPtr<OSString> reasonString;
10944 OSSharedPtr<OSDictionary> dict;
10945 uint64_t timestamp;
10946 bool addWakeReason;
10947
10948 if (!device || !reason) {
10949 return;
10950 }
10951
10952 pmEventTimeStamp(×tamp);
10953
10954 uint64_t args[3] = {};
10955 strlcpy((char *)args, reason, sizeof(args));
10956 kdebugTrace(kPMLogClaimSystemWake, args[0], args[1], args[2], device->getRegistryEntryID());
10957
10958 IOOptionBits aotFlags = 0;
10959 bool needAOTEvaluate = FALSE;
10960
10961 if (kIOPMAOTModeAddEventFlags & _aotMode) {
10962 // Only allow lingering in AOT_STATE for the two wake reasons used for the wrist raise gesture.
10963 if (strcmp("AOP.OutboxNotEmpty", reason) && strcmp("spu_gesture", reason)) {
10964 flags |= kIOPMWakeEventAOTExit;
10965 }
10966 }
10967
10968 #if DEVELOPMENT || DEBUG
10969 if (_aotLingerTime && !strcmp("rtc", reason)) {
10970 flags |= kIOPMWakeEventAOTPossibleExit;
10971 }
10972 #endif /* DEVELOPMENT || DEBUG */
10973
10974 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10975 // Publishing the WakeType is serialized by the PM work loop
10976 if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
10977 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10978 (void *) _nextScheduledAlarmType.get());
10979 }
10980
10981 // Workaround for the missing wake HID event
10982 if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
10983 if (!strcmp("trackpadkeyboard", reason)) {
10984 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10985 (void *) gIOPMWakeTypeUserKey.get());
10986 }
10987 }
10988 #endif
10989
10990 deviceName = device->copyName(gIOServicePlane);
10991 deviceRegId = OSNumber::withNumber(device->getRegistryEntryID(), 64);
10992 claimTime = OSNumber::withNumber(timestamp, 64);
10993 flagsData = OSData::withValue(flags);
10994 reasonString = OSString::withCString(reason);
10995 dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
10996 if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
10997 goto done;
10998 }
10999
11000 dict->setObject(gIONameKey, deviceName.get());
11001 dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
11002 dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
11003 dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
11004 dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
11005 if (details) {
11006 dict->setObject(kIOPMWakeEventDetailsKey, details);
11007 }
11008
11009 WAKEEVENT_LOCK();
11010 addWakeReason = _acceptSystemWakeEvents;
11011 if (_aotMode) {
11012 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
11013 }
11014 aotFlags = (kIOPMWakeEventAOTFlags & flags);
11015 aotFlags = (aotFlags & ~_aotPendingFlags);
11016 needAOTEvaluate = false;
11017 if (_aotNow && aotFlags) {
11018 if (kIOPMWakeEventAOTPossibleExit & flags) {
11019 _aotMetrics->possibleCount++;
11020 _aotAnalytics->possibleCount++;
11021 }
11022 if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
11023 _aotMetrics->confirmedPossibleCount++;
11024 _aotAnalytics->confirmedPossibleCount++;
11025 }
11026 if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
11027 _aotMetrics->rejectedPossibleCount++;
11028 _aotAnalytics->rejectedPossibleCount++;
11029 }
11030 if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
11031 _aotMetrics->expiredPossibleCount++;
11032 _aotAnalytics->expiredPossibleCount++;
11033 }
11034
11035 _aotPendingFlags |= aotFlags;
11036 addWakeReason = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
11037 needAOTEvaluate = _aotReadyToFullWake;
11038 }
11039 DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
11040 reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
11041 _aotNow, pmTracer->getTracePhase(), addWakeReason);
11042
11043 #if DEVELOPMENT || DEBUG
11044 if (addWakeReason) {
11045 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11046 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11047 "Report System Wake Event",
11048 "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
11049 reason,
11050 (int)flags,
11051 deviceName->getCStringNoCopy(),
11052 device->getRegistryEntryID()
11053 );
11054 }
11055 #endif /* DEVELOPMENT || DEBUG */
11056
11057 if (!gWakeReasonSysctlRegistered) {
11058 // Lazy registration until the platform driver stops registering
11059 // the same name.
11060 gWakeReasonSysctlRegistered = true;
11061 }
11062 if (addWakeReason) {
11063 _systemWakeEventsArray->setObject(dict.get());
11064 if (gWakeReasonString[0] != '\0') {
11065 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
11066 }
11067 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
11068 }
11069
11070 WAKEEVENT_UNLOCK();
11071 if (needAOTEvaluate) {
11072 // Call aotEvaluate() on PM work loop since it may call
11073 // aotExit() which accesses PM state.
11074 pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
11075 }
11076
11077 done:
11078 return;
11079 }
11080
11081 //******************************************************************************
11082 // claimSystemBootEvent
11083 //
11084 // For a driver to claim a device is the source/conduit of a system boot event.
11085 //******************************************************************************
11086
11087 void
11088 IOPMrootDomain::claimSystemBootEvent(
11089 IOService * device,
11090 IOOptionBits flags,
11091 const char * reason,
11092 __unused OSObject * details )
11093 {
11094 if (!device || !reason) {
11095 return;
11096 }
11097
11098 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11099 #if DEVELOPMENT || DEBUG
11100 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11101 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11102 "Report System Boot Device",
11103 "Reason: %s Flags: 0x%x Device: %s",
11104 reason,
11105 (int)flags,
11106 device->getName()
11107 );
11108 #endif /* DEVELOPMENT || DEBUG */
11109 WAKEEVENT_LOCK();
11110 if (!gBootReasonSysctlRegistered) {
11111 // Lazy sysctl registration after setting gBootReasonString
11112 strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
11113 os_atomic_store(&gBootReasonSysctlRegistered, true, release);
11114 }
11115 WAKEEVENT_UNLOCK();
11116 }
11117
11118 //******************************************************************************
11119 // claimSystemShutdownEvent
11120 //
11121 // For drivers to claim a system shutdown event on the ensuing boot.
11122 //******************************************************************************
11123
11124 void
11125 IOPMrootDomain::claimSystemShutdownEvent(
11126 IOService * device,
11127 IOOptionBits flags,
11128 const char * reason,
11129 __unused OSObject * details )
11130 {
11131 if (!device || !reason) {
11132 return;
11133 }
11134
11135 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11136 #if DEVELOPMENT || DEBUG
11137 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11138 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11139 "Report System Shutdown Cause From Previous Boot",
11140 "Reason: %s Flags: 0x%x Device: %s",
11141 reason,
11142 (int)flags,
11143 device->getName()
11144 );
11145 #endif /* DEVELOPMENT || DEBUG */
11146 WAKEEVENT_LOCK();
11147 if (gShutdownReasonString[0] != '\0') {
11148 strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11149 }
11150 strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11151
11152 gShutdownReasonSysctlRegistered = true;
11153 WAKEEVENT_UNLOCK();
11154 }
11155
11156 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11157
11158 // MARK: -
11159 // MARK: PMSettingHandle
11160
11161 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11162
11163 void
11164 PMSettingHandle::free( void )
11165 {
11166 if (pmso) {
11167 pmso->clientHandleFreed();
11168 pmso->release();
11169 pmso = NULL;
11170 }
11171
11172 OSObject::free();
11173 }
11174
11175 // MARK: -
11176 // MARK: PMSettingObject
11177
11178 #undef super
11179 #define super OSObject
11180 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11181
11182 /*
11183 * Static constructor/initializer for PMSettingObject
11184 */
11185 PMSettingObject *PMSettingObject::pmSettingObject(
11186 IOPMrootDomain * parent_arg,
11187 IOPMSettingControllerCallback handler_arg,
11188 OSObject * target_arg,
11189 uintptr_t refcon_arg,
11190 uint32_t supportedPowerSources,
11191 const OSSymbol * settings[],
11192 OSObject * *handle_obj)
11193 {
11194 uint32_t settingCount = 0;
11195 PMSettingObject *pmso = NULL;
11196 PMSettingHandle *pmsh = NULL;
11197
11198 if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11199 return NULL;
11200 }
11201
11202 // count OSSymbol entries in NULL terminated settings array
11203 while (settings[settingCount]) {
11204 settingCount++;
11205 }
11206 if (0 == settingCount) {
11207 return NULL;
11208 }
11209
11210 pmso = new PMSettingObject;
11211 if (!pmso || !pmso->init()) {
11212 goto fail;
11213 }
11214
11215 pmsh = new PMSettingHandle;
11216 if (!pmsh || !pmsh->init()) {
11217 goto fail;
11218 }
11219
11220 queue_init(&pmso->calloutQueue);
11221 pmso->parent = parent_arg;
11222 pmso->func = handler_arg;
11223 pmso->target = target_arg;
11224 pmso->refcon = refcon_arg;
11225 pmso->settingCount = settingCount;
11226
11227 pmso->retain(); // handle holds a retain on pmso
11228 pmsh->pmso = pmso;
11229 pmso->pmsh = pmsh;
11230
11231 pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11232 if (pmso->publishedFeatureID) {
11233 for (unsigned int i = 0; i < settingCount; i++) {
11234 // Since there is now at least one listener to this setting, publish
11235 // PM root domain support for it.
11236 parent_arg->publishPMSetting( settings[i],
11237 supportedPowerSources, &pmso->publishedFeatureID[i] );
11238 }
11239 }
11240
11241 *handle_obj = pmsh;
11242 return pmso;
11243
11244 fail:
11245 if (pmso) {
11246 pmso->release();
11247 }
11248 if (pmsh) {
11249 pmsh->release();
11250 }
11251 return NULL;
11252 }
11253
11254 void
11255 PMSettingObject::free( void )
11256 {
11257 if (publishedFeatureID) {
11258 for (const auto& featureID : publishedFeatureID) {
11259 if (featureID) {
11260 parent->removePublishedFeature( featureID );
11261 }
11262 }
11263
11264 publishedFeatureID = {};
11265 }
11266
11267 super::free();
11268 }
11269
11270 IOReturn
11271 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11272 {
11273 return (*func)(target, type, object, refcon);
11274 }
11275
11276 void
11277 PMSettingObject::clientHandleFreed( void )
11278 {
11279 parent->deregisterPMSettingObject(this);
11280 }
11281
11282 // MARK: -
11283 // MARK: PMAssertionsTracker
11284
11285 //*********************************************************************************
11286 //*********************************************************************************
11287 //*********************************************************************************
11288 // class PMAssertionsTracker Implementation
11289
11290 #define kAssertUniqueIDStart 500
11291
11292 PMAssertionsTracker *
11293 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11294 {
11295 PMAssertionsTracker *me;
11296
11297 me = new PMAssertionsTracker;
11298 if (!me || !me->init()) {
11299 if (me) {
11300 me->release();
11301 }
11302 return NULL;
11303 }
11304
11305 me->owner = rootDomain;
11306 me->issuingUniqueID = kAssertUniqueIDStart;
11307 me->assertionsArray = OSArray::withCapacity(5);
11308 me->assertionsKernel = 0;
11309 me->assertionsUser = 0;
11310 me->assertionsCombined = 0;
11311 me->assertionsArrayLock = IOLockAlloc();
11312 me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11313
11314 assert(me->assertionsArray);
11315 assert(me->assertionsArrayLock);
11316
11317 return me;
11318 }
11319
11320 /* tabulate
11321 * - Update assertionsKernel to reflect the state of all
11322 * assertions in the kernel.
11323 * - Update assertionsCombined to reflect both kernel & user space.
11324 */
11325 void
11326 PMAssertionsTracker::tabulate(void)
11327 {
11328 int i;
11329 int count;
11330 const PMAssertStruct *_a = nullptr;
11331 OSValueObject<PMAssertStruct> *_d = nullptr;
11332
11333 IOPMDriverAssertionType oldKernel = assertionsKernel;
11334 IOPMDriverAssertionType oldCombined = assertionsCombined;
11335
11336 ASSERT_GATED();
11337
11338 assertionsKernel = 0;
11339 assertionsCombined = 0;
11340
11341 if (!assertionsArray) {
11342 return;
11343 }
11344
11345 if ((count = assertionsArray->getCount())) {
11346 for (i = 0; i < count; i++) {
11347 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11348 if (_d) {
11349 _a = _d->getBytesNoCopy();
11350 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11351 assertionsKernel |= _a->assertionBits;
11352 }
11353 }
11354 }
11355 }
11356
11357 tabulateProducerCount++;
11358 assertionsCombined = assertionsKernel | assertionsUser;
11359
11360 if ((assertionsKernel != oldKernel) ||
11361 (assertionsCombined != oldCombined)) {
11362 owner->evaluateAssertions(assertionsCombined, oldCombined);
11363 }
11364 }
11365
11366 void
11367 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11368 {
11369 AbsoluteTime now;
11370 uint64_t nsec;
11371
11372 if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11373 (assertStruct->assertCPUStartTime == 0)) {
11374 return;
11375 }
11376
11377 now = mach_absolute_time();
11378 SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11379 absolutetime_to_nanoseconds(now, &nsec);
11380 assertStruct->assertCPUDuration += nsec;
11381 assertStruct->assertCPUStartTime = 0;
11382
11383 if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11384 maxAssertCPUDuration = assertStruct->assertCPUDuration;
11385 maxAssertCPUEntryId = assertStruct->registryEntryID;
11386 }
11387 }
11388
11389 void
11390 PMAssertionsTracker::reportCPUBitAccounting( void )
11391 {
11392 const PMAssertStruct *_a = nullptr;
11393 OSValueObject<PMAssertStruct> *_d = nullptr;
11394 int i, count;
11395 AbsoluteTime now;
11396 uint64_t nsec;
11397
11398 ASSERT_GATED();
11399
11400 // Account for drivers that are still holding the CPU assertion
11401 if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11402 now = mach_absolute_time();
11403 if ((count = assertionsArray->getCount())) {
11404 for (i = 0; i < count; i++) {
11405 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11406 if (_d) {
11407 _a = _d->getBytesNoCopy();
11408 if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11409 (_a->level == kIOPMDriverAssertionLevelOn) &&
11410 (_a->assertCPUStartTime != 0)) {
11411 // Don't modify PMAssertStruct, leave that
11412 // for updateCPUBitAccounting()
11413 SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11414 absolutetime_to_nanoseconds(now, &nsec);
11415 nsec += _a->assertCPUDuration;
11416 if (nsec > maxAssertCPUDuration) {
11417 maxAssertCPUDuration = nsec;
11418 maxAssertCPUEntryId = _a->registryEntryID;
11419 }
11420 }
11421 }
11422 }
11423 }
11424 }
11425
11426 if (maxAssertCPUDuration) {
11427 DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11428 (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11429 }
11430
11431 maxAssertCPUDuration = 0;
11432 maxAssertCPUEntryId = 0;
11433 }
11434
11435 void
11436 PMAssertionsTracker::publishProperties( void )
11437 {
11438 OSSharedPtr<OSArray> assertionsSummary;
11439
11440 if (tabulateConsumerCount != tabulateProducerCount) {
11441 IOLockLock(assertionsArrayLock);
11442
11443 tabulateConsumerCount = tabulateProducerCount;
11444
11445 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11446 */
11447 assertionsSummary = copyAssertionsArray();
11448 if (assertionsSummary) {
11449 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11450 } else {
11451 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11452 }
11453
11454 /* Publish the IOPMrootDomain property "DriverPMAssertions"
11455 */
11456 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11457
11458 IOLockUnlock(assertionsArrayLock);
11459 }
11460 }
11461
11462 PMAssertStruct *
11463 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11464 {
11465 PMAssertStruct *_a = NULL;
11466 OSValueObject<PMAssertStruct> *_d = nullptr;
11467 int found = -1;
11468 int count = 0;
11469 int i = 0;
11470
11471 if (assertionsArray
11472 && (count = assertionsArray->getCount())) {
11473 for (i = 0; i < count; i++) {
11474 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11475 if (_d) {
11476 _a = _d->getMutableBytesNoCopy();
11477 if (_a && (_id == _a->id)) {
11478 found = i;
11479 break;
11480 }
11481 }
11482 }
11483 }
11484
11485 if (-1 == found) {
11486 return NULL;
11487 } else {
11488 if (index) {
11489 *index = found;
11490 }
11491 return _a;
11492 }
11493 }
11494
11495 /* PMAssertionsTracker::handleCreateAssertion
11496 * Perform assertion work on the PM workloop. Do not call directly.
11497 */
11498 IOReturn
11499 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11500 {
11501 PMAssertStruct *assertStruct = nullptr;
11502
11503 ASSERT_GATED();
11504
11505 if (newAssertion) {
11506 IOLockLock(assertionsArrayLock);
11507 assertStruct = newAssertion->getMutableBytesNoCopy();
11508 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11509 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11510 assertStruct->assertCPUStartTime = mach_absolute_time();
11511 }
11512 assertionsArray->setObject(newAssertion);
11513 IOLockUnlock(assertionsArrayLock);
11514 newAssertion->release();
11515
11516 tabulate();
11517 }
11518 return kIOReturnSuccess;
11519 }
11520
11521 /* PMAssertionsTracker::createAssertion
11522 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11523 * appropiate.
11524 */
11525 IOReturn
11526 PMAssertionsTracker::createAssertion(
11527 IOPMDriverAssertionType which,
11528 IOPMDriverAssertionLevel level,
11529 IOService *serviceID,
11530 const char *whoItIs,
11531 IOPMDriverAssertionID *outID)
11532 {
11533 OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11534 PMAssertStruct track;
11535
11536 // Warning: trillions and trillions of created assertions may overflow the unique ID.
11537 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11538 track.level = level;
11539 track.assertionBits = which;
11540
11541 // NB: ownerString is explicitly managed by PMAssertStruct
11542 // it will be released in `handleReleaseAssertion' below
11543 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11544 track.ownerService = serviceID;
11545 track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11546 track.modifiedTime = 0;
11547 pmEventTimeStamp(&track.createdTime);
11548 track.assertCPUStartTime = 0;
11549 track.assertCPUDuration = 0;
11550
11551 dataStore = OSValueObjectWithValue(track);
11552 if (!dataStore) {
11553 if (track.ownerString) {
11554 track.ownerString->release();
11555 track.ownerString = NULL;
11556 }
11557 return kIOReturnNoMemory;
11558 }
11559
11560 *outID = track.id;
11561
11562 if (owner && owner->pmPowerStateQueue) {
11563 // queue action is responsible for releasing dataStore
11564 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11565 }
11566
11567 return kIOReturnSuccess;
11568 }
11569
11570 /* PMAssertionsTracker::handleReleaseAssertion
11571 * Runs in PM workloop. Do not call directly.
11572 */
11573 IOReturn
11574 PMAssertionsTracker::handleReleaseAssertion(
11575 IOPMDriverAssertionID _id)
11576 {
11577 ASSERT_GATED();
11578
11579 int index;
11580 PMAssertStruct *assertStruct = detailsForID(_id, &index);
11581
11582 if (!assertStruct) {
11583 return kIOReturnNotFound;
11584 }
11585
11586 IOLockLock(assertionsArrayLock);
11587
11588 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11589 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11590 updateCPUBitAccounting(assertStruct);
11591 }
11592
11593 if (assertStruct->ownerString) {
11594 assertStruct->ownerString->release();
11595 assertStruct->ownerString = NULL;
11596 }
11597
11598 assertionsArray->removeObject(index);
11599 IOLockUnlock(assertionsArrayLock);
11600
11601 tabulate();
11602 return kIOReturnSuccess;
11603 }
11604
11605 /* PMAssertionsTracker::releaseAssertion
11606 * Releases an assertion and affects system behavior if appropiate.
11607 * Actual work happens on PM workloop.
11608 */
11609 IOReturn
11610 PMAssertionsTracker::releaseAssertion(
11611 IOPMDriverAssertionID _id)
11612 {
11613 if (owner && owner->pmPowerStateQueue) {
11614 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11615 }
11616 return kIOReturnSuccess;
11617 }
11618
11619 /* PMAssertionsTracker::handleSetAssertionLevel
11620 * Runs in PM workloop. Do not call directly.
11621 */
11622 IOReturn
11623 PMAssertionsTracker::handleSetAssertionLevel(
11624 IOPMDriverAssertionID _id,
11625 IOPMDriverAssertionLevel _level)
11626 {
11627 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
11628
11629 ASSERT_GATED();
11630
11631 if (!assertStruct) {
11632 return kIOReturnNotFound;
11633 }
11634
11635 IOLockLock(assertionsArrayLock);
11636 pmEventTimeStamp(&assertStruct->modifiedTime);
11637 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11638 (assertStruct->level != _level)) {
11639 if (_level == kIOPMDriverAssertionLevelOn) {
11640 assertStruct->assertCPUStartTime = mach_absolute_time();
11641 } else {
11642 updateCPUBitAccounting(assertStruct);
11643 }
11644 }
11645 assertStruct->level = _level;
11646 IOLockUnlock(assertionsArrayLock);
11647
11648 tabulate();
11649 return kIOReturnSuccess;
11650 }
11651
11652 /* PMAssertionsTracker::setAssertionLevel
11653 */
11654 IOReturn
11655 PMAssertionsTracker::setAssertionLevel(
11656 IOPMDriverAssertionID _id,
11657 IOPMDriverAssertionLevel _level)
11658 {
11659 if (owner && owner->pmPowerStateQueue) {
11660 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11661 (void *)(uintptr_t)_level, _id);
11662 }
11663
11664 return kIOReturnSuccess;
11665 }
11666
11667 IOReturn
11668 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11669 {
11670 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11671
11672 ASSERT_GATED();
11673
11674 if (new_user_levels != assertionsUser) {
11675 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11676 assertionsUser = new_user_levels;
11677 }
11678
11679 tabulate();
11680 return kIOReturnSuccess;
11681 }
11682
11683 IOReturn
11684 PMAssertionsTracker::setUserAssertionLevels(
11685 IOPMDriverAssertionType new_user_levels)
11686 {
11687 if (gIOPMWorkLoop) {
11688 gIOPMWorkLoop->runAction(
11689 OSMemberFunctionCast(
11690 IOWorkLoop::Action,
11691 this,
11692 &PMAssertionsTracker::handleSetUserAssertionLevels),
11693 this,
11694 (void *) &new_user_levels, NULL, NULL, NULL);
11695 }
11696
11697 return kIOReturnSuccess;
11698 }
11699
11700
11701 OSSharedPtr<OSArray>
11702 PMAssertionsTracker::copyAssertionsArray(void)
11703 {
11704 int count;
11705 int i;
11706 OSSharedPtr<OSArray> outArray = NULL;
11707
11708 if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11709 goto exit;
11710 }
11711 outArray = OSArray::withCapacity(count);
11712 if (!outArray) {
11713 goto exit;
11714 }
11715
11716 for (i = 0; i < count; i++) {
11717 const PMAssertStruct *_a = nullptr;
11718 OSValueObject<PMAssertStruct> *_d = nullptr;
11719 OSSharedPtr<OSDictionary> details;
11720
11721 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11722 if (_d && (_a = _d->getBytesNoCopy())) {
11723 OSSharedPtr<OSNumber> _n;
11724
11725 details = OSDictionary::withCapacity(7);
11726 if (!details) {
11727 continue;
11728 }
11729
11730 outArray->setObject(details.get());
11731
11732 _n = OSNumber::withNumber(_a->id, 64);
11733 if (_n) {
11734 details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11735 }
11736 _n = OSNumber::withNumber(_a->createdTime, 64);
11737 if (_n) {
11738 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11739 }
11740 _n = OSNumber::withNumber(_a->modifiedTime, 64);
11741 if (_n) {
11742 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11743 }
11744 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11745 if (_n) {
11746 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11747 }
11748 _n = OSNumber::withNumber(_a->level, 64);
11749 if (_n) {
11750 details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11751 }
11752 _n = OSNumber::withNumber(_a->assertionBits, 64);
11753 if (_n) {
11754 details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11755 }
11756
11757 if (_a->ownerString) {
11758 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11759 }
11760 }
11761 }
11762
11763 exit:
11764 return os::move(outArray);
11765 }
11766
11767 IOPMDriverAssertionType
11768 PMAssertionsTracker::getActivatedAssertions(void)
11769 {
11770 return assertionsCombined;
11771 }
11772
11773 IOPMDriverAssertionLevel
11774 PMAssertionsTracker::getAssertionLevel(
11775 IOPMDriverAssertionType type)
11776 {
11777 // FIXME: unused and also wrong
11778 if (type && ((type & assertionsKernel) == assertionsKernel)) {
11779 return kIOPMDriverAssertionLevelOn;
11780 } else {
11781 return kIOPMDriverAssertionLevelOff;
11782 }
11783 }
11784
11785 //*********************************************************************************
11786 //*********************************************************************************
11787 //*********************************************************************************
11788
11789
11790 static void
11791 pmEventTimeStamp(uint64_t *recordTS)
11792 {
11793 clock_sec_t tsec;
11794 clock_usec_t tusec;
11795
11796 if (!recordTS) {
11797 return;
11798 }
11799
11800 // We assume tsec fits into 32 bits; 32 bits holds enough
11801 // seconds for 136 years since the epoch in 1970.
11802 clock_get_calendar_microtime(&tsec, &tusec);
11803
11804
11805 // Pack the sec & microsec calendar time into a uint64_t, for fun.
11806 *recordTS = 0;
11807 *recordTS |= (uint32_t)tusec;
11808 *recordTS |= ((uint64_t)tsec << 32);
11809
11810 return;
11811 }
11812
11813 // MARK: -
11814 // MARK: IORootParent
11815
11816 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11817
11818 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11819
11820 // The reason that root domain needs a root parent is to facilitate demand
11821 // sleep, since a power change from the root parent cannot be vetoed.
11822 //
11823 // The above statement is no longer true since root domain now performs
11824 // demand sleep using overrides. But root parent remains to avoid changing
11825 // the power tree stacking. Root parent is parked at the max power state.
11826
11827
11828 static IOPMPowerState patriarchPowerStates[2] =
11829 {
11830 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11831 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11832 };
11833
11834 void
11835 IORootParent::initialize( void )
11836 {
11837
11838 gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
11839 gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
11840 gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
11841 gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
11842 gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
11843 gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
11844 gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
11845 gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
11846 gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
11847 gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
11848 gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
11849 gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
11850 gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
11851 gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
11852 gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
11853 gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
11854 gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
11855 gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
11856 gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
11857 gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
11858 gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
11859 gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
11860 gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
11861 gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
11862 gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
11863 gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
11864 gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
11865 gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
11866 gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
11867 gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
11868 gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
11869 gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
11870 gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
11871 gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
11872 gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
11873 gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
11874 gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
11875 gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
11876 gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
11877 gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
11878 gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
11879 gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
11880 gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
11881 gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
11882 }
11883
11884 bool
11885 IORootParent::start( IOService * nub )
11886 {
11887 IOService::start(nub);
11888 attachToParent( getRegistryRoot(), gIOPowerPlane );
11889 PMinit();
11890 registerPowerDriver(this, patriarchPowerStates, 2);
11891 makeUsable();
11892 return true;
11893 }
11894
11895 void
11896 IORootParent::shutDownSystem( void )
11897 {
11898 }
11899
11900 void
11901 IORootParent::restartSystem( void )
11902 {
11903 }
11904
11905 void
11906 IORootParent::sleepSystem( void )
11907 {
11908 }
11909
11910 void
11911 IORootParent::dozeSystem( void )
11912 {
11913 }
11914
11915 void
11916 IORootParent::sleepToDoze( void )
11917 {
11918 }
11919
11920 void
11921 IORootParent::wakeSystem( void )
11922 {
11923 }
11924
11925 OSSharedPtr<OSObject>
11926 IORootParent::copyProperty( const char * aKey) const
11927 {
11928 return IOService::copyProperty(aKey);
11929 }
11930
11931 uint32_t
11932 IOPMrootDomain::getWatchdogTimeout()
11933 {
11934 if (gSwdSleepWakeTimeout) {
11935 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11936 }
11937 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11938 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11939 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11940 } else {
11941 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11942 }
11943 }
11944
11945 static void
11946 reportAnalyticsTimerExpired(
11947 thread_call_param_t us, thread_call_param_t )
11948 {
11949 ((IOPMrootDomain *)us)->reportAnalytics();
11950 }
11951
11952 void
11953 IOPMrootDomain::initAOTMetrics()
11954 {
11955 if (!_aotMetrics) {
11956 _aotMetrics = IOMallocType(IOPMAOTMetrics);
11957 }
11958
11959 if (!_aotAnalytics) {
11960 _aotAnalytics = IOMallocType(IOPMAOTAnalytics);
11961 analyticsThreadCall = thread_call_allocate_with_options(reportAnalyticsTimerExpired,
11962 (thread_call_param_t)this, THREAD_CALL_PRIORITY_KERNEL, THREAD_CALL_OPTIONS_ONCE);
11963 scheduleAnalyticsThreadCall();
11964 }
11965 }
11966
11967 #define ANALYTICS_PERIOD_HOURS 24
11968 #define ANALYTICS_LEEWAY_MINUTES 5
11969
11970 void
11971 IOPMrootDomain::scheduleAnalyticsThreadCall()
11972 {
11973 uint64_t leeway, period, leeway_ns, period_ns, deadline;
11974
11975 period_ns = ANALYTICS_PERIOD_HOURS * 60 * 60 * NSEC_PER_SEC;
11976 leeway_ns = ANALYTICS_LEEWAY_MINUTES * 60 * NSEC_PER_SEC;
11977
11978 nanoseconds_to_absolutetime(period_ns, &period);
11979 nanoseconds_to_absolutetime(leeway_ns, &leeway);
11980 deadline = mach_continuous_time() + period;
11981 thread_call_enter_delayed_with_leeway(analyticsThreadCall, NULL, deadline, leeway, THREAD_CALL_CONTINUOUS);
11982 }
11983
11984 CA_EVENT(aot_analytics,
11985 CA_INT, possible_count,
11986 CA_INT, confirmed_possible_count,
11987 CA_INT, rejected_possible_count,
11988 CA_INT, expired_possible_count);
11989
11990 void
11991 IOPMrootDomain::reportAnalytics()
11992 {
11993 if (_aotAnalytics) {
11994 IOLog("IOPMAOTAnalytics possibleCount: %u, confirmedPossibleCount: %u, rejectedPossibleCount: %u, expiredPossibleCount: %u\n",
11995 _aotAnalytics->possibleCount, _aotAnalytics->confirmedPossibleCount, _aotAnalytics->rejectedPossibleCount, _aotAnalytics->expiredPossibleCount);
11996
11997 ca_event_t event = CA_EVENT_ALLOCATE(aot_analytics);
11998 CA_EVENT_TYPE(aot_analytics) * e = (CA_EVENT_TYPE(aot_analytics) *)event->data;
11999 e->possible_count = _aotAnalytics->possibleCount;
12000 e->confirmed_possible_count = _aotAnalytics->confirmedPossibleCount;
12001 e->rejected_possible_count = _aotAnalytics->rejectedPossibleCount;
12002 e->expired_possible_count = _aotAnalytics->expiredPossibleCount;
12003 CA_EVENT_SEND(event);
12004
12005 bzero(_aotAnalytics, sizeof(IOPMAOTAnalytics));
12006 scheduleAnalyticsThreadCall();
12007 }
12008 }
12009
12010 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
12011 IOReturn
12012 IOPMrootDomain::restartWithStackshot()
12013 {
12014 takeStackshot(true);
12015
12016 return kIOReturnSuccess;
12017 }
12018
12019 void
12020 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
12021 {
12022 takeStackshot(wdogTrigger);
12023 }
12024
12025 void
12026 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
12027 {
12028 switch (tracePhase) {
12029 case kIOPMTracePointSleepStarted:
12030 *phaseString = "kIOPMTracePointSleepStarted";
12031 *description = "starting sleep";
12032 break;
12033
12034 case kIOPMTracePointSleepApplications:
12035 *phaseString = "kIOPMTracePointSleepApplications";
12036 *description = "notifying applications";
12037 break;
12038
12039 case kIOPMTracePointSleepPriorityClients:
12040 *phaseString = "kIOPMTracePointSleepPriorityClients";
12041 *description = "notifying clients about upcoming system capability changes";
12042 break;
12043
12044 case kIOPMTracePointSleepWillChangeInterests:
12045 *phaseString = "kIOPMTracePointSleepWillChangeInterests";
12046 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
12047 break;
12048
12049 case kIOPMTracePointSleepPowerPlaneDrivers:
12050 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
12051 *description = "calling power state change callbacks";
12052 break;
12053
12054 case kIOPMTracePointSleepDidChangeInterests:
12055 *phaseString = "kIOPMTracePointSleepDidChangeInterests";
12056 *description = "calling rootDomain's clients about rootDomain's state changes";
12057 break;
12058
12059 case kIOPMTracePointSleepCapabilityClients:
12060 *phaseString = "kIOPMTracePointSleepCapabilityClients";
12061 *description = "notifying clients about current system capabilities";
12062 break;
12063
12064 case kIOPMTracePointSleepPlatformActions:
12065 *phaseString = "kIOPMTracePointSleepPlatformActions";
12066 *description = "calling Quiesce/Sleep action callbacks";
12067 break;
12068
12069 case kIOPMTracePointSleepCPUs:
12070 {
12071 *phaseString = "kIOPMTracePointSleepCPUs";
12072 #if defined(__i386__) || defined(__x86_64__)
12073 /*
12074 * We cannot use the getCPUNumber() method to get the cpu number, since
12075 * that cpu number is unrelated to the cpu number we need (we need the cpu
12076 * number as enumerated by the scheduler, NOT the CPU number enumerated
12077 * by ACPIPlatform as the CPUs are enumerated in MADT order).
12078 * Instead, pass the Mach processor pointer associated with the current
12079 * shutdown target so its associated cpu_id can be used in
12080 * processor_to_datastring.
12081 */
12082 if (currentShutdownTarget != NULL &&
12083 currentShutdownTarget->getMachProcessor() != NULL) {
12084 const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
12085 currentShutdownTarget->getMachProcessor());
12086 *description = sbuf;
12087 } else {
12088 *description = "halting all non-boot CPUs";
12089 }
12090 #else
12091 *description = "halting all non-boot CPUs";
12092 #endif
12093 break;
12094 }
12095 case kIOPMTracePointSleepPlatformDriver:
12096 *phaseString = "kIOPMTracePointSleepPlatformDriver";
12097 *description = "executing platform specific code";
12098 break;
12099
12100 case kIOPMTracePointHibernate:
12101 *phaseString = "kIOPMTracePointHibernate";
12102 *description = "writing the hibernation image";
12103 break;
12104
12105 case kIOPMTracePointSystemSleep:
12106 *phaseString = "kIOPMTracePointSystemSleep";
12107 *description = "in EFI/Bootrom after last point of entry to sleep";
12108 break;
12109
12110 case kIOPMTracePointWakePlatformDriver:
12111 *phaseString = "kIOPMTracePointWakePlatformDriver";
12112 *description = "executing platform specific code";
12113 break;
12114
12115
12116 case kIOPMTracePointWakePlatformActions:
12117 *phaseString = "kIOPMTracePointWakePlatformActions";
12118 *description = "calling Wake action callbacks";
12119 break;
12120
12121 case kIOPMTracePointWakeCPUs:
12122 *phaseString = "kIOPMTracePointWakeCPUs";
12123 *description = "starting non-boot CPUs";
12124 break;
12125
12126 case kIOPMTracePointWakeWillPowerOnClients:
12127 *phaseString = "kIOPMTracePointWakeWillPowerOnClients";
12128 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
12129 break;
12130
12131 case kIOPMTracePointWakeWillChangeInterests:
12132 *phaseString = "kIOPMTracePointWakeWillChangeInterests";
12133 *description = "calling rootDomain's clients about upcoming rootDomain's state changes";
12134 break;
12135
12136 case kIOPMTracePointWakeDidChangeInterests:
12137 *phaseString = "kIOPMTracePointWakeDidChangeInterests";
12138 *description = "calling rootDomain's clients about completed rootDomain's state changes";
12139 break;
12140
12141 case kIOPMTracePointWakePowerPlaneDrivers:
12142 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
12143 *description = "calling power state change callbacks";
12144 break;
12145
12146 case kIOPMTracePointWakeCapabilityClients:
12147 *phaseString = "kIOPMTracePointWakeCapabilityClients";
12148 *description = "informing clients about current system capabilities";
12149 break;
12150
12151 case kIOPMTracePointWakeApplications:
12152 *phaseString = "kIOPMTracePointWakeApplications";
12153 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
12154 break;
12155
12156 case kIOPMTracePointDarkWakeEntry:
12157 *phaseString = "kIOPMTracePointDarkWakeEntry";
12158 *description = "entering darkwake on way to sleep";
12159 break;
12160
12161 case kIOPMTracePointDarkWakeExit:
12162 *phaseString = "kIOPMTracePointDarkWakeExit";
12163 *description = "entering fullwake from darkwake";
12164 break;
12165
12166 default:
12167 *phaseString = NULL;
12168 *description = NULL;
12169 }
12170 }
12171
12172 void
12173 IOPMrootDomain::saveFailureData2File()
12174 {
12175 unsigned int len = 0;
12176 char failureStr[512];
12177 errno_t error;
12178 char *outbuf;
12179 OSNumber *statusCode;
12180 uint64_t pmStatusCode = 0;
12181 uint32_t phaseData = 0;
12182 uint32_t phaseDetail = 0;
12183 bool efiFailure = false;
12184
12185 OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
12186 statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
12187 if (statusCode) {
12188 pmStatusCode = statusCode->unsigned64BitValue();
12189 phaseData = pmStatusCode & 0xFFFFFFFF;
12190 phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
12191 if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
12192 LOG("Sleep Wake failure in EFI\n");
12193 efiFailure = true;
12194 failureStr[0] = 0;
12195 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);
12196 len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12197 }
12198 }
12199
12200 if (!efiFailure) {
12201 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12202 swd_flags |= SWD_BOOT_BY_SW_WDOG;
12203 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12204 // dump panic will handle saving nvram data
12205 return;
12206 }
12207
12208 /* Keeping this around for capturing data during power
12209 * button press */
12210
12211 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12212 DLOG("No sleep wake failure string\n");
12213 return;
12214 }
12215 if (len == 0) {
12216 DLOG("Ignoring zero byte SleepWake failure string\n");
12217 goto exit;
12218 }
12219
12220 // if PMStatus code is zero, delete stackshot and return
12221 if (statusCode) {
12222 if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12223 // there was no sleep wake failure
12224 // this can happen if delete stackshot was called
12225 // before take stackshot completed. Let us delete any
12226 // sleep wake failure data in nvram
12227 DLOG("Deleting stackshot on successful wake\n");
12228 deleteStackshot();
12229 return;
12230 }
12231 }
12232
12233 if (len > sizeof(failureStr)) {
12234 len = sizeof(failureStr);
12235 }
12236 failureStr[0] = 0;
12237 PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12238 }
12239 if (failureStr[0] != 0) {
12240 error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12241 if (error) {
12242 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12243 } else {
12244 DLOG("Saved SleepWake failure string to file.\n");
12245 }
12246 }
12247
12248 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12249 goto exit;
12250 }
12251
12252 if (swd_buffer) {
12253 unsigned int len = 0;
12254 errno_t error;
12255 char nvram_var_name_buffer[20];
12256 unsigned int concat_len = 0;
12257 swd_hdr *hdr = NULL;
12258
12259
12260 hdr = (swd_hdr *)swd_buffer;
12261 outbuf = (char *)hdr + hdr->spindump_offset;
12262 OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12263
12264 for (int i = 0; i < 8; i++) {
12265 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12266 if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12267 LOG("No SleepWake blob to read beyond chunk %d\n", i);
12268 break;
12269 }
12270 if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12271 PERemoveNVRAMProperty(nvram_var_name_buffer);
12272 LOG("Could not read the property :-(\n");
12273 break;
12274 }
12275 PERemoveNVRAMProperty(nvram_var_name_buffer);
12276 concat_len += len;
12277 }
12278 LOG("Concatenated length for the SWD blob %d\n", concat_len);
12279
12280 if (concat_len) {
12281 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12282 if (error) {
12283 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12284 } else {
12285 LOG("Saved SleepWake zipped data to file.\n");
12286 }
12287 } else {
12288 // There is a sleep wake failure string but no stackshot
12289 // Write a placeholder stacks file so that swd runs
12290 snprintf(outbuf, 20, "%s", "No stackshot data\n");
12291 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12292 if (error) {
12293 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12294 } else {
12295 LOG("Saved SleepWake zipped data to file.\n");
12296 }
12297 }
12298 } else {
12299 LOG("No buffer allocated to save failure stackshot\n");
12300 }
12301
12302
12303 gRootDomain->swd_lock = 0;
12304 exit:
12305 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12306 return;
12307 }
12308
12309
12310 void
12311 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12312 {
12313 OSSharedPtr<IORegistryIterator> iter;
12314 OSSharedPtr<const OSSymbol> kextName = NULL;
12315 IORegistryEntry * entry;
12316 IOService * node;
12317 bool nodeFound = false;
12318
12319 const void * callMethod = NULL;
12320 const char * objectName = NULL;
12321 uint32_t timeout = getWatchdogTimeout();
12322 const char * phaseString = NULL;
12323 const char * phaseDescription = NULL;
12324
12325 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12326 uint32_t tracePhase = pmTracer->getTracePhase();
12327
12328 *thread = NULL;
12329 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12330 snprintf(failureStr, strLen, "Sleep transition timed out after %d seconds", timeout);
12331 } else {
12332 snprintf(failureStr, strLen, "Wake transition timed out after %d seconds", timeout);
12333 }
12334 tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12335
12336 if (notifierThread) {
12337 if (notifier && (notifier->identifier)) {
12338 objectName = notifier->identifier->getCStringNoCopy();
12339 }
12340 *thread = notifierThread;
12341 } else {
12342 iter = IORegistryIterator::iterateOver(
12343 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12344
12345 if (iter) {
12346 while ((entry = iter->getNextObject())) {
12347 node = OSDynamicCast(IOService, entry);
12348 if (!node) {
12349 continue;
12350 }
12351 if (OSDynamicCast(IOPowerConnection, node)) {
12352 continue;
12353 }
12354
12355 if (node->getBlockingDriverCall(thread, &callMethod)) {
12356 nodeFound = true;
12357 break;
12358 }
12359 }
12360 }
12361 if (nodeFound) {
12362 kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12363 if (kextName) {
12364 objectName = kextName->getCStringNoCopy();
12365 }
12366 }
12367 }
12368 if (phaseDescription) {
12369 strlcat(failureStr, " while ", strLen);
12370 strlcat(failureStr, phaseDescription, strLen);
12371 strlcat(failureStr, ".", strLen);
12372 }
12373 if (objectName) {
12374 strlcat(failureStr, " Suspected bundle: ", strLen);
12375 strlcat(failureStr, objectName, strLen);
12376 strlcat(failureStr, ".", strLen);
12377 }
12378 if (*thread) {
12379 char threadName[40];
12380 snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12381 strlcat(failureStr, threadName, strLen);
12382 }
12383
12384 DLOG("%s\n", failureStr);
12385 }
12386
12387 struct swd_stackshot_compressed_data {
12388 z_output_func zoutput;
12389 size_t zipped;
12390 uint64_t totalbytes;
12391 uint64_t lastpercent;
12392 IOReturn error;
12393 unsigned outremain;
12394 unsigned outlen;
12395 unsigned writes;
12396 Bytef * outbuf;
12397 };
12398 struct swd_stackshot_compressed_data swd_zip_var = { };
12399
12400 static void *
12401 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12402 {
12403 void *result;
12404 LOG("Alloc in zipping %d items of size %d\n", items, size);
12405
12406 result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12407 swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12408 LOG("Offset %zu\n", swd_zs_zoffset);
12409 return result;
12410 }
12411
12412 static int
12413 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12414 {
12415 unsigned len;
12416
12417 len = strm->avail_in;
12418
12419 if (len > size) {
12420 len = size;
12421 }
12422 if (len == 0) {
12423 return 0;
12424 }
12425
12426 if (strm->next_in != (Bytef *) strm) {
12427 memcpy(buf, strm->next_in, len);
12428 } else {
12429 bzero(buf, len);
12430 }
12431
12432 strm->adler = z_crc32(strm->adler, buf, len);
12433
12434 strm->avail_in -= len;
12435 strm->next_in += len;
12436 strm->total_in += len;
12437
12438 return (int)len;
12439 }
12440
12441 static int
12442 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12443 {
12444 unsigned int i = 0;
12445 // if outlen > max size don't add to the buffer
12446 assert(buf != NULL);
12447 if (strm && buf) {
12448 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12449 LOG("No space to GZIP... not writing to NVRAM\n");
12450 return len;
12451 }
12452 }
12453 for (i = 0; i < len; i++) {
12454 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12455 }
12456 swd_zip_var.outlen += len;
12457 return len;
12458 }
12459
12460 static void
12461 swd_zs_free(void * __unused ref, void * __unused ptr)
12462 {
12463 }
12464
12465 static int
12466 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12467 {
12468 int wbits = 12;
12469 int memlevel = 3;
12470
12471 if (((unsigned int) numBytes) != numBytes) {
12472 return 0;
12473 }
12474
12475 if (!swd_zs.zalloc) {
12476 swd_zs.zalloc = swd_zs_alloc;
12477 swd_zs.zfree = swd_zs_free;
12478 if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12479 // allocation failed
12480 bzero(&swd_zs, sizeof(swd_zs));
12481 // swd_zs_zoffset = 0;
12482 } else {
12483 LOG("PMRD inited the zlib allocation routines\n");
12484 }
12485 }
12486
12487 swd_zip_var.zipped = 0;
12488 swd_zip_var.totalbytes = 0; // should this be the max that we have?
12489 swd_zip_var.lastpercent = 0;
12490 swd_zip_var.error = kIOReturnSuccess;
12491 swd_zip_var.outremain = 0;
12492 swd_zip_var.outlen = 0;
12493 swd_zip_var.writes = 0;
12494 swd_zip_var.outbuf = (Bytef *)outPtr;
12495
12496 swd_zip_var.totalbytes = numBytes;
12497
12498 swd_zs.avail_in = 0;
12499 swd_zs.next_in = NULL;
12500 swd_zs.avail_out = 0;
12501 swd_zs.next_out = NULL;
12502
12503 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12504
12505 z_stream *zs;
12506 int zr;
12507 zs = &swd_zs;
12508
12509 while (swd_zip_var.error >= 0) {
12510 if (!zs->avail_in) {
12511 zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12512 zs->avail_in = (unsigned int) numBytes;
12513 }
12514 if (!zs->avail_out) {
12515 zs->next_out = (Bytef *)zs;
12516 zs->avail_out = UINT32_MAX;
12517 }
12518 zr = deflate(zs, Z_NO_FLUSH);
12519 if (Z_STREAM_END == zr) {
12520 break;
12521 }
12522 if (zr != Z_OK) {
12523 LOG("ZERR %d\n", zr);
12524 swd_zip_var.error = zr;
12525 } else {
12526 if (zs->total_in == numBytes) {
12527 break;
12528 }
12529 }
12530 }
12531
12532 //now flush the stream
12533 while (swd_zip_var.error >= 0) {
12534 if (!zs->avail_out) {
12535 zs->next_out = (Bytef *)zs;
12536 zs->avail_out = UINT32_MAX;
12537 }
12538 zr = deflate(zs, Z_FINISH);
12539 if (Z_STREAM_END == zr) {
12540 break;
12541 }
12542 if (zr != Z_OK) {
12543 LOG("ZERR %d\n", zr);
12544 swd_zip_var.error = zr;
12545 } else {
12546 if (zs->total_in == numBytes) {
12547 LOG("Total output size %d\n", swd_zip_var.outlen);
12548 break;
12549 }
12550 }
12551 }
12552
12553 return swd_zip_var.outlen;
12554 }
12555
12556 void
12557 IOPMrootDomain::deleteStackshot()
12558 {
12559 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12560 // takeStackshot hasn't completed
12561 return;
12562 }
12563 LOG("Deleting any sleepwake failure data in nvram\n");
12564
12565 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12566 char nvram_var_name_buf[20];
12567 for (int i = 0; i < 8; i++) {
12568 snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12569 if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12570 LOG("Removing %s returned false\n", nvram_var_name_buf);
12571 }
12572 }
12573 // force NVRAM sync
12574 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12575 DLOG("Failed to force nvram sync\n");
12576 }
12577 gRootDomain->swd_lock = 0;
12578 }
12579
12580 void
12581 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12582 {
12583 swd_hdr * hdr = NULL;
12584 int cnt = 0;
12585 int max_cnt;
12586 pid_t pid = 0;
12587 kern_return_t kr = KERN_SUCCESS;
12588 uint64_t flags;
12589
12590 char * dstAddr;
12591 uint32_t size;
12592 uint32_t bytesRemaining;
12593 unsigned bytesWritten = 0;
12594
12595 char failureStr[512];
12596 thread_t thread = NULL;
12597 const char * swfPanic = "swfPanic";
12598
12599 uint32_t bufSize;
12600 int success = 0;
12601
12602 #if defined(__i386__) || defined(__x86_64__)
12603 const bool concise = false;
12604 #else
12605 const bool concise = true;
12606 #endif
12607
12608 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12609 return;
12610 }
12611
12612 failureStr[0] = 0;
12613 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12614 return;
12615 }
12616
12617 if (wdogTrigger) {
12618 getFailureData(&thread, failureStr, sizeof(failureStr));
12619
12620 if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12621 goto skip_stackshot;
12622 }
12623 } else {
12624 AbsoluteTime now;
12625 uint64_t nsec;
12626 clock_get_uptime(&now);
12627 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12628 absolutetime_to_nanoseconds(now, &nsec);
12629 snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12630 }
12631
12632 if (swd_buffer == NULL) {
12633 sleepWakeDebugMemAlloc();
12634 if (swd_buffer == NULL) {
12635 return;
12636 }
12637 }
12638 hdr = (swd_hdr *)swd_buffer;
12639 bufSize = hdr->alloc_size;
12640
12641 dstAddr = (char*)hdr + hdr->spindump_offset;
12642 flags = STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_THREAD_WAITINFO | STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12643
12644 /* If not wdogTrigger only take kernel tasks stackshot
12645 */
12646 if (wdogTrigger) {
12647 pid = -1;
12648 max_cnt = 3;
12649 } else {
12650 pid = 0;
12651 max_cnt = 2;
12652 }
12653
12654 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12655 * If we run out of space, take stackshot with only kernel task
12656 */
12657 while (success == 0 && cnt < max_cnt) {
12658 bytesRemaining = bufSize - hdr->spindump_offset;
12659 cnt++;
12660 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12661
12662 size = bytesRemaining;
12663 kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12664 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12665 kr, pid, size, flags, bytesWritten);
12666 if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12667 if (pid == -1) {
12668 pid = 0;
12669 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12670 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12671 } else {
12672 LOG("Insufficient buffer size for only kernel task\n");
12673 break;
12674 }
12675 }
12676 if (kr == KERN_SUCCESS) {
12677 if (bytesWritten == 0) {
12678 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12679 continue;
12680 }
12681 bytesRemaining -= bytesWritten;
12682 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12683
12684 memset(hdr->reason, 0x20, sizeof(hdr->reason));
12685
12686 // Compress stackshot and save to NVRAM
12687 {
12688 char *outbuf = (char *)swd_compressed_buffer;
12689 int outlen = 0;
12690 int num_chunks = 0;
12691 int max_chunks = 0;
12692 int leftover = 0;
12693 char nvram_var_name_buffer[20];
12694
12695 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12696
12697 if (outlen) {
12698 max_chunks = outlen / (2096 - 200);
12699 leftover = outlen % (2096 - 200);
12700
12701 if (max_chunks < 8) {
12702 for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
12703 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12704 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
12705 LOG("Failed to update NVRAM %d\n", num_chunks);
12706 break;
12707 }
12708 }
12709 if (leftover) {
12710 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12711 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
12712 LOG("Failed to update NVRAM with leftovers\n");
12713 }
12714 }
12715 success = 1;
12716 LOG("Successfully saved stackshot to NVRAM\n");
12717 } else {
12718 if (pid == -1) {
12719 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12720 pid = 0;
12721 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12722 LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
12723 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12724 } else {
12725 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12726 break;
12727 }
12728 }
12729 }
12730 }
12731 }
12732 }
12733
12734 if (failureStr[0]) {
12735 // append sleep-wake failure code
12736 char traceCode[80];
12737 snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
12738 pmTracer->getTraceData(), pmTracer->getTracePhase());
12739 strlcat(failureStr, traceCode, sizeof(failureStr));
12740 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
12741 DLOG("Failed to write SleepWake failure string\n");
12742 }
12743 }
12744
12745 // force NVRAM sync
12746 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12747 DLOG("Failed to force nvram sync\n");
12748 }
12749
12750 skip_stackshot:
12751 if (wdogTrigger) {
12752 if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
12753 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
12754 // If current boot is due to this watch dog trigger restart in previous boot,
12755 // then don't trigger again until at least 1 successful sleep & wake.
12756 if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
12757 LOG("Shutting down due to repeated Sleep/Wake failures\n");
12758 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12759 PEHaltRestart(kPEHaltCPU);
12760 return;
12761 }
12762 }
12763 if (gSwdPanic == 0) {
12764 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12765 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12766 PEHaltRestart(kPERestartCPU);
12767 }
12768 }
12769 if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12770 DLOG("Failed to write SleepWake failure panic key\n");
12771 }
12772 #if defined(__x86_64__)
12773 if (thread) {
12774 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12775 } else
12776 #endif /* defined(__x86_64__) */
12777 {
12778 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12779 }
12780 } else {
12781 gRootDomain->swd_lock = 0;
12782 return;
12783 }
12784 }
12785
12786 void
12787 IOPMrootDomain::sleepWakeDebugMemAlloc()
12788 {
12789 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12790
12791 swd_hdr *hdr = NULL;
12792 void *bufPtr = NULL;
12793
12794 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12795
12796
12797 if (kIOSleepWakeWdogOff & gIOKitDebug) {
12798 return;
12799 }
12800
12801 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12802 return;
12803 }
12804
12805 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12806 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12807 size);
12808 if (memDesc == NULL) {
12809 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12810 goto exit;
12811 }
12812
12813 bufPtr = memDesc->getBytesNoCopy();
12814
12815 // Carve out memory for zlib routines
12816 swd_zs_zmem = (vm_offset_t)bufPtr;
12817 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12818
12819 // Carve out memory for compressed stackshots
12820 swd_compressed_buffer = bufPtr;
12821 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12822
12823 // Remaining is used for holding stackshot
12824 hdr = (swd_hdr *)bufPtr;
12825 memset(hdr, 0, sizeof(swd_hdr));
12826
12827 hdr->signature = SWD_HDR_SIGNATURE;
12828 hdr->alloc_size = SWD_STACKSHOT_SIZE;
12829
12830 hdr->spindump_offset = sizeof(swd_hdr);
12831 swd_buffer = (void *)hdr;
12832 swd_memDesc = os::move(memDesc);
12833 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
12834
12835 exit:
12836 gRootDomain->swd_lock = 0;
12837 }
12838
12839 void
12840 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12841 {
12842 #if UNUSED
12843 vm_size_t size = SWD_SPINDUMP_SIZE;
12844
12845 swd_hdr *hdr = NULL;
12846
12847 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12848
12849 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12850 return;
12851 }
12852
12853 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12854 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12855 SWD_SPINDUMP_SIZE);
12856
12857 if (memDesc == NULL) {
12858 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12859 goto exit;
12860 }
12861
12862
12863 hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12864 memset(hdr, 0, sizeof(swd_hdr));
12865
12866 hdr->signature = SWD_HDR_SIGNATURE;
12867 hdr->alloc_size = size;
12868
12869 hdr->spindump_offset = sizeof(swd_hdr);
12870 swd_spindump_buffer = (void *)hdr;
12871 swd_spindump_memDesc = os::move(memDesc);
12872
12873 exit:
12874 gRootDomain->swd_lock = 0;
12875 #endif /* UNUSED */
12876 }
12877
12878 void
12879 IOPMrootDomain::sleepWakeDebugEnableWdog()
12880 {
12881 }
12882
12883 bool
12884 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12885 {
12886 return !systemBooting && !systemShutdown && !gWillShutdown;
12887 }
12888
12889 void
12890 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12891 {
12892 swd_hdr *hdr = NULL;
12893 errno_t error = EIO;
12894
12895 if (swd_spindump_buffer && gSpinDumpBufferFull) {
12896 hdr = (swd_hdr *)swd_spindump_buffer;
12897
12898 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12899 (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12900
12901 if (error) {
12902 return;
12903 }
12904
12905 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12906 (char*)hdr + offsetof(swd_hdr, UUID),
12907 sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12908
12909 gSpinDumpBufferFull = false;
12910 }
12911 }
12912
12913 errno_t
12914 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12915 {
12916 struct vnode *vp = NULL;
12917 vfs_context_t ctx = vfs_context_create(vfs_context_current());
12918 kauth_cred_t cred = vfs_context_ucred(ctx);
12919 struct vnode_attr va;
12920 errno_t error = EIO;
12921
12922 if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
12923 S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
12924 LOG("Failed to open the file %s\n", name);
12925 swd_flags |= SWD_FILEOP_ERROR;
12926 goto exit;
12927 }
12928 VATTR_INIT(&va);
12929 VATTR_WANTED(&va, va_nlink);
12930 /* Don't dump to non-regular files or files with links. */
12931 if (vp->v_type != VREG ||
12932 vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
12933 LOG("Bailing as this is not a regular file\n");
12934 swd_flags |= SWD_FILEOP_ERROR;
12935 goto exit;
12936 }
12937 VATTR_INIT(&va);
12938 VATTR_SET(&va, va_data_size, 0);
12939 vnode_setattr(vp, &va, ctx);
12940
12941
12942 if (buf != NULL) {
12943 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12944 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12945 if (error != 0) {
12946 LOG("Failed to save sleep wake log. err 0x%x\n", error);
12947 swd_flags |= SWD_FILEOP_ERROR;
12948 } else {
12949 DLOG("Saved %d bytes to file %s\n", len, name);
12950 }
12951 }
12952
12953 exit:
12954 if (vp) {
12955 vnode_close(vp, FWRITE, ctx);
12956 }
12957 if (ctx) {
12958 vfs_context_rele(ctx);
12959 }
12960
12961 return error;
12962 }
12963
12964 #else /* defined(__i386__) || defined(__x86_64__) */
12965
12966 void
12967 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12968 {
12969 if (restart) {
12970 if (gSwdPanic == 0) {
12971 return;
12972 }
12973 panic("Sleep/Wake hang detected");
12974 return;
12975 }
12976 }
12977
12978 void
12979 IOPMrootDomain::takeStackshot(bool restart)
12980 {
12981 #pragma unused(restart)
12982 }
12983
12984 void
12985 IOPMrootDomain::deleteStackshot()
12986 {
12987 }
12988
12989 void
12990 IOPMrootDomain::sleepWakeDebugMemAlloc()
12991 {
12992 }
12993
12994 void
12995 IOPMrootDomain::saveFailureData2File()
12996 {
12997 }
12998
12999 void
13000 IOPMrootDomain::sleepWakeDebugEnableWdog()
13001 {
13002 }
13003
13004 bool
13005 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
13006 {
13007 return false;
13008 }
13009
13010 void
13011 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
13012 {
13013 }
13014
13015 errno_t
13016 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
13017 {
13018 return 0;
13019 }
13020
13021 #endif /* defined(__i386__) || defined(__x86_64__) */
13022
13023