}
extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
extern "C" addr64_t kvtophys(vm_offset_t va);
-extern "C" int stack_snapshot_from_kernel(pid_t pid, void *buf, uint32_t size, uint32_t flags, unsigned *bytesTraced);
static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
static void notifySystemShutdown( IOService * root, uint32_t messageType );
#define kDefaultWranglerIdlePeriod 25 // in milliseconds
#define kIOSleepWakeDebugKey "Persistent-memory-note"
+#define kIOEFIBootRomFailureKey "wake-failure"
#define kRD_AllPowerSources (kIOPMSupportedOnAC \
| kIOPMSupportedOnBatt \
static char gWakeReasonString[128];
static bool gWakeReasonSysctlRegistered = false;
+static AbsoluteTime gIOLastWakeAbsTime;
+static AbsoluteTime gIOLastSleepAbsTime;
#if defined(__i386__) || defined(__x86_64__)
static bool gSpinDumpBufferFull = false;
static PMTraceWorker *tracer( IOPMrootDomain * );
void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
void tracePoint(uint8_t phase);
- void tracePoint(uint8_t phase, uint8_t data8);
void traceDetail(uint32_t detail);
- void traceLoginWindowPhase(uint8_t phase);
+ void traceComponentWakeProgress(uint32_t component, uint32_t data);
int recordTopLevelPCIDevice(IOService *);
void RTC_TRACE(void);
virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
IOPMTracePointHandler tracePointHandler;
void * tracePointTarget;
uint64_t getPMStatusCode();
+ uint8_t getTracePhase();
+ uint32_t getTraceData();
private:
IOPMrootDomain *owner;
- IOLock *pciMappingLock;
+ IOLock *pmTraceWorkerLock;
OSArray *pciDeviceBitMappings;
uint8_t addedToRegistry;
uint8_t tracePhase;
- uint8_t loginWindowPhase;
- uint8_t traceData8;
uint32_t traceData32;
+ uint8_t loginWindowData;
+ uint8_t coreDisplayData;
+ uint8_t coreGraphicsData;
};
/*
//******************************************************************************
+static void swdDebugSetupCallout( thread_call_param_t p0, thread_call_param_t p1 )
+{
+ IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
+ uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
+
+ rootDomain->swdDebugSetup();
+
+ if (p1) {
+ rootDomain->allowPowerChange(notifyRef);
+ }
+ DLOG("swdDebugSetupCallout finish\n");
+}
+
+void IOPMrootDomain::swdDebugSetup( )
+{
+#if HIBERNATION
+ static int32_t mem_only = -1;
+ if ((mem_only == -1) &&
+ (PE_parse_boot_argn("swd_mem_only", &mem_only, sizeof(mem_only)) == false)) {
+ mem_only = 0;
+ }
+
+ if ((mem_only == 1) || (gRootDomain->sleepWakeDebugIsWdogEnabled() == false)) {
+ return;
+ }
+ DLOG("swdDebugSetup state:%d\n", swd_DebugImageSetup);
+ if (swd_DebugImageSetup == FALSE) {
+ swd_DebugImageSetup = TRUE;
+ IOOpenDebugDataFile(kSleepWakeStackBinFilename, SWD_BUF_SIZE);
+ }
+#endif
+
+
+}
+
+static void swdDebugTeardownCallout( thread_call_param_t p0, thread_call_param_t p1 )
+{
+ IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
+ uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
+
+ rootDomain->swdDebugTeardown();
+ if (p1) {
+ rootDomain->allowPowerChange(notifyRef);
+ }
+ DLOG("swdDebugTeardownCallout finish\n");
+}
+
+void IOPMrootDomain::swdDebugTeardown( )
+{
+
+#if HIBERNATION
+ DLOG("swdDebugTeardown state:%d\n", swd_DebugImageSetup);
+ if (swd_DebugImageSetup == TRUE) {
+ swd_DebugImageSetup = FALSE;
+ IOCloseDebugDataFile();
+ }
+#endif
+
+
+}
+//******************************************************************************
+
+
static void disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
{
IOService * rootDomain = (IOService *) p0;
if (ON_STATE == powerState)
{
sync_internal();
+ swdDebugSetupCallout(p0, NULL);
}
#if HIBERNATION
else
{
+ swdDebugTeardownCallout(p0, NULL);
IOHibernateSystemPostWake();
if (gRootDomain)
}
//******************************************************************************
-
-static void hib_debugSetup_callout( thread_call_param_t p0, thread_call_param_t p1 )
-{
- IOService * rootDomain = (IOService *) p0;
- uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
-
-#if HIBERNATION
- IOOpenDebugDataFile(kSleepWakeStackBinFilename, SWD_BUF_SIZE);
-#endif
-
- rootDomain->allowPowerChange(notifyRef);
- DLOG("hib_debugSetup_callout finish\n");
-}
-//******************************************************************************
-
static UInt32 computeDeltaTimeMS( const AbsoluteTime * startTime )
{
AbsoluteTime endTime;
CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
&gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
+SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD|CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
+SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD|CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
static int
sysctl_willshutdown
diskSyncCalloutEntry = thread_call_allocate(
&disk_sync_callout,
(thread_call_param_t) this);
- hibDebugSetupEntry = thread_call_allocate(
- &hib_debugSetup_callout,
+ swdDebugSetupEntry = thread_call_allocate(
+ &swdDebugSetupCallout,
+ (thread_call_param_t) this);
+ swdDebugTearDownEntry = thread_call_allocate(
+ &swdDebugTeardownCallout,
(thread_call_param_t) this);
-
updateConsoleUsersEntry = thread_call_allocate(
&updateConsoleUsersCallout,
(thread_call_param_t) this);
preventSystemSleepList = OSSet::withCapacity(2);
PMinit(); // creates gIOPMWorkLoop
+ gIOPMWorkLoop = getIOPMWorkloop();
// Create IOPMPowerStateQueue used to queue external power
// events, and to handle those events on the PM work loop.
pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
this, OSMemberFunctionCast(IOEventSource::Action, this,
&IOPMrootDomain::dispatchPowerEvent));
- getPMworkloop()->addEventSource(pmPowerStateQueue);
-#ifdef CHECK_THREAD_CONTEXT
- gIOPMWorkLoop = getPMworkloop();
-#endif
+ gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
// create our power parent
patriarch = new IORootParent;
const OSSymbol *idle_seconds_string = OSSymbol::withCString("System Idle Seconds");
const OSSymbol *sleepdisabled_string = OSSymbol::withCString("SleepDisabled");
const OSSymbol *ondeck_sleepwake_uuid_string = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
- const OSSymbol *loginwindow_tracepoint_string = OSSymbol::withCString(kIOPMLoginWindowSecurityDebugKey);
+ const OSSymbol *loginwindow_progress_string = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
+ const OSSymbol *coredisplay_progress_string = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
+ const OSSymbol *coregraphics_progress_string = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
#if HIBERNATION
const OSSymbol *hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey);
const OSSymbol *hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey);
obj->retain();
pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
}
- else if (key->isEqualTo(loginwindow_tracepoint_string))
+ else if (key->isEqualTo(loginwindow_progress_string))
{
- if (pmTracer && (n = OSDynamicCast(OSNumber, obj)))
- pmTracer->traceLoginWindowPhase(n->unsigned8BitValue());
+ if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
+ uint32_t data = n->unsigned32BitValue();
+ pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
+ kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
+ }
+ }
+ else if (key->isEqualTo(coredisplay_progress_string))
+ {
+ if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
+ uint32_t data = n->unsigned32BitValue();
+ pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
+ kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
+ }
+ }
+ else if (key->isEqualTo(coregraphics_progress_string))
+ {
+ if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
+ uint32_t data = n->unsigned32BitValue();
+ pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
+ kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
+ }
}
else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
if(idle_seconds_string) idle_seconds_string->release();
if(sleepdisabled_string) sleepdisabled_string->release();
if(ondeck_sleepwake_uuid_string) ondeck_sleepwake_uuid_string->release();
- if(loginwindow_tracepoint_string) loginwindow_tracepoint_string->release();
+ if(loginwindow_progress_string) loginwindow_progress_string->release();
+ if(coredisplay_progress_string) coredisplay_progress_string->release();
+ if(coregraphics_progress_string) coregraphics_progress_string->release();
#if HIBERNATION
if(hibernatemode_string) hibernatemode_string->release();
if(hibernatefile_string) hibernatefile_string->release();
if (!connect || !connect->getReadyFlag())
continue;
- if ((service = (IOService *) connect->copyChildEntry(gIOPowerPlane)))
+ if ((service = OSDynamicCast(IOService, connect->copyChildEntry(gIOPowerPlane))))
{
if (service->assertPMDriverCall(&callEntry))
{
thread_call_cancel(extraSleepTimer);
idleSleepTimerPending = false;
- if (!assertOnWakeSecs && systemWakeTime) {
+ if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
AbsoluteTime now;
clock_usec_t microsecs;
clock_get_uptime(&now);
- SUB_ABSOLUTETIME(&now, &systemWakeTime);
+ SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
if (assertOnWakeReport) {
HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
void IOPMrootDomain::handleSleepTimerExpiration( void )
{
- if (!getPMworkloop()->inGate())
+ if (!gIOPMWorkLoop->inGate())
{
- getPMworkloop()->runAction(
+ gIOPMWorkLoop->runAction(
OSMemberFunctionCast(IOWorkLoop::Action, this,
&IOPMrootDomain::handleSleepTimerExpiration),
this);
gIOLastSleepTime.tv_usec = microsecs;
gIOLastWakeTime.tv_sec = 0;
gIOLastWakeTime.tv_usec = 0;
+ gIOLastSleepAbsTime = now;
if (wake2DarkwakeDelay && sleepDelaysReport) {
clock_usec_t microsecs;
}
assertOnWakeSecs = 0;
((IOService *)this)->stop_watchdog_timer(); //14456299
+ lowBatteryCondition = false;
+
getPlatform()->sleepKernel();
// The CPU(s) are off at this point,
// Code will resume execution here upon wake.
- clock_get_uptime(&systemWakeTime);
+ clock_get_uptime(&gIOLastWakeAbsTime);
+ IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
_highestCapability = 0;
((IOService *)this)->start_watchdog_timer(); //14456299
LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
#endif
- // log system wake
- PMDebug(kPMLogSystemWake, 0, 0);
- lowBatteryCondition = false;
lastSleepReason = 0;
_lastDebugWakeSeconds = _debugWakeSeconds;
_debugWakeSeconds = 0;
_scheduledAlarms = 0;
-#ifndef __LP64__
- systemWake();
-#endif
-
#if defined(__i386__) || defined(__x86_64__)
+ kdebugTrace(kPMLogSystemWake, 0, 0, 0);
wranglerTickled = false;
graphicsSuppressed = false;
darkWakePostTickle = false;
}
}
#else /* !__i386__ && !__x86_64__ */
+ kdebugTrace(kPMLogSystemWake, 0, ml_get_wake_timebase() >> 32, ml_get_wake_timebase());
// stay awake for at least 30 seconds
wranglerTickled = true;
fullWakeReason = kFullWakeReasonLocalUser;
}
#endif
+ MSG("prevent idle sleep list: %s%c (%u)\n",
+ service->getName(),
+ (addNotRemove) ? '+' : '-', newCount);
return true;
}
preventSystemSleepList->setObject(service);
DLOG("prevent system sleep list: %s+ (%u)\n",
service->getName(), preventSystemSleepList->getCount());
- if (!assertOnWakeSecs && systemWakeTime) {
+ if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
AbsoluteTime now;
clock_usec_t microsecs;
clock_get_uptime(&now);
- SUB_ABSOLUTETIME(&now, &systemWakeTime);
+ SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
if (assertOnWakeReport) {
HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
OSObject *object = NULL;
OSArray *array = NULL;
- if (!getPMworkloop()->inGate())
+ if (!gIOPMWorkLoop->inGate())
{
- getPMworkloop()->runAction(
+ gIOPMWorkLoop->runAction(
OSMemberFunctionCast(IOWorkLoop::Action, this,
&IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
this, (void *)idleSleepList, (void *)systemSleepList);
}
}
+#define CAP_WILL_CHANGE_TO_OFF(params, flag) \
+ (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
+ ((params)->fromCapabilities & (flag)) && \
+ (((params)->toCapabilities & (flag)) == 0))
+
+#define CAP_DID_CHANGE_TO_ON(params, flag) \
+ (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
+ ((params)->toCapabilities & (flag)) && \
+ (((params)->fromCapabilities & (flag)) == 0))
+
+#define CAP_DID_CHANGE_TO_OFF(params, flag) \
+ (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
+ ((params)->fromCapabilities & (flag)) && \
+ (((params)->toCapabilities & (flag)) == 0))
+
+#define CAP_WILL_CHANGE_TO_ON(params, flag) \
+ (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
+ ((params)->toCapabilities & (flag)) && \
+ (((params)->fromCapabilities & (flag)) == 0))
+
//******************************************************************************
// sysPowerDownHandler
//
if (messageType == kIOMessageSystemWillSleep)
{
#if HIBERNATION
- static int32_t mem_only = -1;
IOPowerStateChangeNotification *notify =
- (IOPowerStateChangeNotification *)messageArgs;
+ (IOPowerStateChangeNotification *)messageArgs;
- if ((mem_only == -1) &&
- (PE_parse_boot_argn("swd_mem_only", &mem_only, sizeof(mem_only)) == false)) {
- mem_only = 0;
- }
- if ((mem_only != 1) && (gRootDomain->sleepWakeDebugIsWdogEnabled()))
- {
- notify->returnValue = 30 * 1000 * 1000;
- thread_call_enter1(
- gRootDomain->hibDebugSetupEntry,
- (thread_call_param_t)(uintptr_t) notify->powerRef);
- }
+ notify->returnValue = 30 * 1000 * 1000;
+ thread_call_enter1(
+ gRootDomain->swdDebugSetupEntry,
+ (thread_call_param_t)(uintptr_t) notify->powerRef);
#endif
}
else if (messageType == kIOMessageSystemCapabilityChange)
params->fromCapabilities, params->toCapabilities,
params->changeFlags);
- if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
- (params->fromCapabilities & kIOPMSystemCapabilityCPU) &&
- (params->toCapabilities & kIOPMSystemCapabilityCPU) == 0)
+ if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU))
{
// We will ack within 20 seconds
params->maxWaitForReply = 20 * 1000 * 1000;
+
+ // Remove EFI/BootRom's previous wake's failure data
+ PERemoveNVRAMProperty(kIOEFIBootRomFailureKey);
+
#if HIBERNATION
gRootDomain->evaluateSystemSleepPolicyEarly();
gRootDomain->diskSyncCalloutEntry,
(thread_call_param_t)(uintptr_t) params->notifyRef);
}
- else
- if ((params->changeFlags & kIOPMSystemCapabilityDidChange) &&
- (params->toCapabilities & kIOPMSystemCapabilityCPU) &&
- (params->fromCapabilities & kIOPMSystemCapabilityCPU) == 0)
- {
#if HIBERNATION
+ else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU))
+ {
// We will ack within 110 seconds
params->maxWaitForReply = 110 * 1000 * 1000;
thread_call_enter1(
gRootDomain->diskSyncCalloutEntry,
(thread_call_param_t)(uintptr_t) params->notifyRef);
-#endif
}
+ else if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityGraphics) ||
+ CAP_WILL_CHANGE_TO_ON(params, kIOPMSystemCapabilityGraphics))
+ {
+ // WillChange for Full wake -> Darkwake
+ params->maxWaitForReply = 30 * 1000 * 1000;
+ thread_call_enter1(
+ gRootDomain->swdDebugSetupEntry,
+ (thread_call_param_t)(uintptr_t) params->notifyRef);
+ }
+ else if (CAP_DID_CHANGE_TO_OFF(params, kIOPMSystemCapabilityGraphics) ||
+ CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityGraphics))
+ {
+ // DidChange for Full wake -> Darkwake
+ params->maxWaitForReply = 30 * 1000 * 1000;
+ thread_call_enter1(
+ gRootDomain->swdDebugTearDownEntry,
+ (thread_call_param_t)(uintptr_t) params->notifyRef);
+
+ }
+#endif
ret = kIOReturnSuccess;
}
fPMSettingsDict->setObject(type, object);
// Prep all PMSetting objects with the given 'type' for callout.
- array = (const OSArray *) settingsCallbacks->getObject(type);
+ array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
if (!array || ((capacity = array->getCount()) == 0))
goto unlock_exit;
PMSETTING_LOCK();
for (i=0; settings[i]; i++)
{
- list = (OSArray *) settingsCallbacks->getObject(settings[i]);
+ list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
if (!list) {
// New array of callbacks for this setting
list = OSArray::withCapacity(1);
{
while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject())))
{
- array = (OSArray *) settingsCallbacks->getObject(sym);
+ array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
index = array->getNextIndexOfObject(pmso, 0);
if (-1 != index) {
array->removeObject(index);
varInfoStruct.varType = vBool;
varInfoStruct.varInitValue = value;
varInfoStruct.varCurValue = value;
- strncpy( (char *)varInfoStruct.varName,
+ strlcpy( (char *)varInfoStruct.varName,
(const char *)varNameStr,
- strlen(varNameStr) + 1 );
+ sizeof(varInfoStruct.varName));
// Set!
pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
currentFactors |= kIOPMSleepFactorBatteryLow;
if (!standbyDelay)
currentFactors |= kIOPMSleepFactorStandbyNoDelay;
- if (!standbyEnabled)
+ if (standbyNixed || !standbyEnabled)
currentFactors |= kIOPMSleepFactorStandbyDisabled;
+ if (resetTimers)
+ {
+ currentFactors |= kIOPMSleepFactorLocalUserActivity;
+ currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
+ }
if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
kIOPMDriverAssertionLevelOff)
currentFactors |= kIOPMSleepFactorUSBExternalDevice;
{
IOPMSystemSleepParameters params;
OSData * paramsData;
-
+ bool wakeNow;
// Evaluate sleep policy after sleeping drivers but before platform sleep.
DLOG("%s\n", __FUNCTION__);
bzero(¶ms, sizeof(params));
+ wakeNow = false;
if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2, &hibernateMode))
{
- if ((hibernateDisabled || hibernateAborted) &&
+ if ((kIOPMSleepTypeStandby == params.sleepType) && gIOHibernateStandbyDisabled)
+ {
+ standbyNixed = true;
+ wakeNow = true;
+ }
+ if (wakeNow
+ || ((hibernateDisabled || hibernateAborted) &&
(getSleepTypeAttributes(params.sleepType) &
- kIOPMSleepAttributeHibernateSetup))
+ kIOPMSleepAttributeHibernateSetup)))
{
// Final evaluation picked a state requiring hibernation,
- // but hibernate setup was skipped. Arm a short sleep using
+ // but hibernate isn't going to proceed. Arm a short sleep using
// the early non-hibernate sleep parameters.
- // Set hibernateRetry flag to force hibernate setup on the
- // next sleep.
-
bcopy(&gEarlySystemSleepParams, ¶ms, sizeof(params));
params.sleepType = kIOPMSleepTypeAbortedSleep;
params.ecWakeTimer = 1;
- hibernateRetry = true;
- DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d\n",
- params.ecWakeTimer, hibernateDisabled, hibernateAborted);
+ gIOHibernateMode = 0;
+ if (standbyNixed)
+ {
+ resetTimers = true;
+ }
+ else
+ {
+ // Set hibernateRetry flag to force hibernate setup on the
+ // next sleep.
+ hibernateRetry = true;
+ }
+ DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
+ params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
}
else
{
hibernateRetry = false;
}
+ if (kIOPMSleepTypeAbortedSleep != params.sleepType)
+ {
+ resetTimers = false;
+ }
+
paramsData = OSData::withBytes(¶ms, sizeof(params));
if (paramsData)
{
_pendingCapability = 0;
capabilityLoss = true;
- // Clear previous stats
- IOLockLock(pmStatsLock);
- if (pmStatsAppResponses)
- {
- pmStatsAppResponses->release();
- pmStatsAppResponses = OSArray::withCapacity(5);
- }
- IOLockUnlock(pmStatsLock);
-
}
else if (kSystemTransitionNewCapClient != _systemTransitionType)
{
// Full to Dark transition.
if (CAP_LOSS(kIOPMSystemCapabilityGraphics))
{
+ // Clear previous stats
+ IOLockLock(pmStatsLock);
+ if (pmStatsAppResponses)
+ {
+ pmStatsAppResponses->release();
+ pmStatsAppResponses = OSArray::withCapacity(5);
+ }
+ IOLockUnlock(pmStatsLock);
+
+
tracePoint( kIOPMTracePointDarkWakeEntry );
*inOutChangeFlags |= kIOPMSyncTellPowerDown;
_systemMessageClientMask = kSystemMessageClientPowerd |
{
// Beginning of a system sleep transition.
// Cancellation is still possible.
- tracePoint( kIOPMTracePointSleepStarted, sleepReason );
+ tracePoint( kIOPMTracePointSleepStarted );
_systemMessageClientMask = kSystemMessageClientAll;
if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0)
(changeFlags & kIOPMNotDone)))
{
setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
- tracePoint( kIOPMTracePointSystemUp, 0 );
+ tracePoint( kIOPMTracePointSystemUp );
}
_systemTransitionType = kSystemTransitionNone;
toldPowerdCapWillChange = false;
logGraphicsClamp = false;
+
+ if (lowBatteryCondition) {
+ privateSleepSystem (kIOPMSleepReasonLowPower);
+ }
}
}
uint64_t nsec;
clock_get_uptime(&now);
- SUB_ABSOLUTETIME(&now, &systemWakeTime);
+ SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
absolutetime_to_nanoseconds(now, &nsec);
if (kIOLogPMRootDomain & gIOKitDebug)
MSG("Graphics suppressed %u ms\n",
protected:
uint32_t ackTimeoutCnt;
+ uint32_t msgType; // Message pending ack
};
bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
bool isCapClient = false;
bool allow = false;
+ IOPMServiceInterestNotifier *notifier;
+ notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
do {
if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
(!isCapMsg || !_joinedCapabilityClients ||
{
// app has not replied yet, wait for it
*((OSObject **) arg3) = kOSBooleanFalse;
+
+ if (notifier) {
+ notifier->msgType = context->messageType;
+ }
}
allow = true;
if (object == (OSObject *) systemCapabilityNotifier)
{
allow = true;
+ if (notifier) {
+ notifier->msgType = context->messageType;
+ }
break;
}
{
if ((object == (OSObject *) systemCapabilityNotifier) &&
CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
- (fullToDarkReason == kIOPMSleepReasonIdle))
+ (fullToDarkReason == kIOPMSleepReasonIdle)) {
+ if (notifier) {
+ notifier->msgType = context->messageType;
+ }
allow = true;
+ }
break;
}
if ((context->notifyType == kNotifyApps) &&
(_systemMessageClientMask & kSystemMessageClientLegacyApp))
{
- IOPMServiceInterestNotifier *notify;
allow = true;
- if ((notify = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object))
- && arg3) {
+ if (notifier) {
+ if (arg3) {
+ if (notifier->ackTimeoutCnt >= 3)
+ *((OSObject **) arg3) = kOSBooleanFalse;
+ else
+ *((OSObject **) arg3) = kOSBooleanTrue;
+ }
- if (notify->ackTimeoutCnt >= 3)
- *((OSObject **) arg3) = kOSBooleanFalse;
- else
- *((OSObject **) arg3) = kOSBooleanTrue;
+ notifier->msgType = context->messageType;
}
}
else if ((context->notifyType == kNotifyPriority) &&
if (matching) matching->release();
if(iter)
{
- wrangler = (IOService *) iter->getNextObject();
+ wrangler = OSDynamicCast(IOService, iter->getNextObject());
iter->release();
}
}
systemCapabilityNotifier->retain();
}
/* intentional fall-through */
+ [[clang::fallthrough]];
case kPowerEventRegisterKernelCapabilityClient:
if (!_joinedCapabilityClients)
if (kFullWakeReasonDisplayOn == fullWakeReason)
fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
+ kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
setProperty(gIOPMUserIsActiveKey, kOSBooleanTrue);
messageClients(kIOPMMessageUserIsActiveChanged);
}
clock_get_uptime(&userBecameInactiveTime);
flags.bit.userBecameInactive = true;
+ kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
setProperty(gIOPMUserIsActiveKey, kOSBooleanFalse);
messageClients(kIOPMMessageUserIsActiveChanged);
}
uint64_t nsec;
clock_get_uptime(&now);
- SUB_ABSOLUTETIME(&now, &systemWakeTime);
+ SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
absolutetime_to_nanoseconds(now, &nsec);
MSG("full wake %s (reason %u) %u ms\n",
promotion ? "promotion" : "request",
{
hibernateRetry = false;
sleepToStandby = false;
+ standbyNixed = false;
+ resetTimers = false;
sleepTimerMaintenance = false;
_systemMessageClientMask = kSystemMessageClientPowerd |
if (changedBits & kIOPMDriverAssertionCPUBit) {
evaluatePolicy(kStimulusDarkWakeEvaluate);
- if (!assertOnWakeSecs && systemWakeTime) {
+ if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
AbsoluteTime now;
clock_usec_t microsecs;
clock_get_uptime(&now);
- SUB_ABSOLUTETIME(&now, &systemWakeTime);
+ SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
if (assertOnWakeReport) {
HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
const char *name,
int messageType,
uint32_t delay_ms,
- int app_pid,
+ uint64_t id,
OSObject *object,
IOPMPowerStateIndex powerState)
{
return;
+ if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow)) {
+ kdebugTrace(kPMLogDrvResponseDelay, id, messageType, delay_ms);
+ }
+ else if (notify) {
+ kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
+ notify->msgType = 0;
+ }
+
responseDescription = OSDictionary::withCapacity(5);
if (responseDescription)
{
}
}
- if (app_pid != -1) {
- pidNum = OSNumber::withNumber(app_pid, 32);
+ if (id != 0) {
+ pidNum = OSNumber::withNumber(id, 32);
if (pidNum) {
responseDescription->setObject(_statsPIDKey, pidNum);
pidNum->release();
void * param1, void * param2,
void * param3, void * param4 )
{
+ uint32_t bootFailureCode = 0xffffffff;
+ unsigned int len = sizeof(bootFailureCode);
if (pmTracer && functionName &&
functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
!pmTracer->tracePointHandler && !pmTracer->tracePointTarget)
pmTracer->tracePointTarget = (void *) param2;
tracePointPCI = (uint32_t)(uintptr_t) param3;
tracePointPhases = (uint32_t)(uintptr_t) param4;
+ if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
+ if (!PEReadNVRAMProperty(kIOEFIBootRomFailureKey, &bootFailureCode, &len)) {
+ MSG("Failed to read failure code from NVRam\n");
+ }
+ // Failure code from EFI/BootRom is a four byte structure
+ tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
+ }
statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
- if ((tracePointPhases >> 24) != kIOPMTracePointSystemUp)
- {
+ if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
MSG("Sleep failure code 0x%08x 0x%08x\n",
tracePointPCI, tracePointPhases);
}
functionName, waitForFunction, param1, param2, param3, param4);
}
+void IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
+ uintptr_t param1, uintptr_t param2, uintptr_t param3)
+{
+ uint32_t code = IODBG_POWER(event);
+ uint64_t regId = id;
+ if (regId == 0) {
+ regId = getRegistryEntryID();
+ }
+ IOTimeStampConstant(code, (uintptr_t) regId, param1, param2, param3);
+}
+
+
void IOPMrootDomain::tracePoint( uint8_t point )
{
if (systemBooting) return;
if (kIOPMTracePointWakeCapabilityClients == point)
acceptSystemWakeEvents(false);
- PMDebug(kPMLogSleepWakeTracePoint, point, 0);
+ kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
pmTracer->tracePoint(point);
}
-void IOPMrootDomain::tracePoint( uint8_t point, uint8_t data )
-{
- if (systemBooting) return;
-
- PMDebug(kPMLogSleepWakeTracePoint, point, data);
- pmTracer->tracePoint(point, data);
-}
-
-void IOPMrootDomain::traceDetail( uint32_t detail )
+void IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uintptr_t handler)
{
- if (!systemBooting)
+ if (!systemBooting) {
+ uint32_t detail = ((msgIndex & 0xff) << 24) |
+ ((msgType & 0xfff) << 12) |
+ (handler & 0xfff);
pmTracer->traceDetail( detail );
+ kdebugTrace(kPMLogSleepWakeTracePoint, 0, pmTracer->getTracePhase(), msgType, handler & 0xfff);
+ }
}
// this dictionary lazily.
me->owner = owner;
me->pciDeviceBitMappings = NULL;
- me->pciMappingLock = IOLockAlloc();
+ me->pmTraceWorkerLock = IOLockAlloc();
me->tracePhase = kIOPMTracePointSystemUp;
- me->loginWindowPhase = 0;
me->traceData32 = 0;
+ me->loginWindowData = 0;
+ me->coreDisplayData = 0;
+ me->coreGraphicsData = 0;
return me;
}
{
uint32_t wordA;
- wordA = (tracePhase << 24) | (loginWindowPhase << 16) |
- (traceData8 << 8);
+ IOLockLock(pmTraceWorkerLock);
+ wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
+ (coreGraphicsData << 8) | tracePhase;
+ IOLockUnlock(pmTraceWorkerLock);
tracePointHandler( tracePointTarget, traceData32, wordA );
_LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
const OSSymbol * deviceName;
int index = -1;
- IOLockLock(pciMappingLock);
+ IOLockLock(pmTraceWorkerLock);
if (!pciDeviceBitMappings)
{
addedToRegistry = owner->setProperty("PCITopLevel", this);
exit:
- IOLockUnlock(pciMappingLock);
+ IOLockUnlock(pmTraceWorkerLock);
return index;
}
bool ok = false;
if (pciDeviceBitMappings)
{
- IOLockLock(pciMappingLock);
+ IOLockLock(pmTraceWorkerLock);
ok = pciDeviceBitMappings->serialize(s);
- IOLockUnlock(pciMappingLock);
+ IOLockUnlock(pmTraceWorkerLock);
}
return ok;
}
RTC_TRACE();
}
-void PMTraceWorker::tracePoint(uint8_t phase, uint8_t data8)
-{
- // clear trace detail when phase begins
- if (tracePhase != phase)
- traceData32 = 0;
-
- tracePhase = phase;
- traceData8 = data8;
-
- DLOG("trace point 0x%02x 0x%02x\n", tracePhase, traceData8);
- RTC_TRACE();
-}
-
void PMTraceWorker::traceDetail(uint32_t detail)
{
- if (kIOPMTracePointSleepPriorityClients != tracePhase)
- return;
traceData32 = detail;
DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
RTC_TRACE();
}
-void PMTraceWorker::traceLoginWindowPhase(uint8_t phase)
+void PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
{
- loginWindowPhase = phase;
-
- DLOG("loginwindow tracepoint 0x%02x\n", loginWindowPhase);
+ switch (component) {
+ case kIOPMLoginWindowProgress:
+ loginWindowData = data & kIOPMLoginWindowProgressMask;
+ break;
+ case kIOPMCoreDisplayProgress:
+ coreDisplayData = data & kIOPMCoreDisplayProgressMask;
+ break;
+ case kIOPMCoreGraphicsProgress:
+ coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
+ break;
+ default:
+ return;
+ }
+
+ DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
RTC_TRACE();
}
traceData32 |= bitMask;
_LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
service->getName(), bitNum, bitMask, traceData32);
+ owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
}
else
{
traceData32 &= ~bitMask;
_LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
service->getName(), bitNum, bitMask, traceData32);
+ owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
}
DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
uint64_t PMTraceWorker::getPMStatusCode( )
{
- return (((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase << 24) |
- (loginWindowPhase << 16) | (traceData8 << 8));
+ return (((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase));
}
+uint8_t PMTraceWorker::getTracePhase()
+{
+ return tracePhase;
+}
+
+uint32_t PMTraceWorker::getTraceData()
+{
+ return traceData32;
+}
+
// MARK: -
// MARK: PMHaltWorker
inner = (OSSet *)gPMHaltArray->getObject(me->depth);
if (inner)
{
- service = (IOService *)inner->getAnyObject();
+ service = OSDynamicCast(IOService, inner->getAnyObject());
if (service)
{
service->retain();
{
swd_hdr * hdr = NULL;
addr64_t data[3];
- uint32_t wdog_panic = 0;
+ int wdog_panic = -1;
int cnt = 0;
pid_t pid = 0;
+ kern_return_t kr = KERN_SUCCESS;
uint32_t flags;
char * dstAddr;
uint32_t size;
uint32_t bytesRemaining;
+ unsigned bytesWritten = 0;
+ unsigned totalBytes = 0;
unsigned int len;
OSString * UUIDstring = NULL;
uint64_t code;
IOMemoryMap * logBufMap = NULL;
- swd_stackshot_hdr *stackshotHdr = NULL;
uint32_t bufSize;
uint32_t initialStackSize;
}
if (wdogTrigger) {
- if (PE_parse_boot_argn("swd_panic", &wdog_panic, sizeof(wdog_panic)) &&
- (wdog_panic == 1)) {
- // If boot-arg is set to panic on sleep/wake hang, call panic
+ PE_parse_boot_argn("swd_panic", &wdog_panic, sizeof(wdog_panic));
+ if (wdog_panic == 1) {
+ // If boot-arg specifies to panic then panic.
panic("Sleep/Wake hang detected\n");
return;
}
if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock))
return;
- if (isSpinDump)
+ if (isSpinDump) {
hdr = (swd_hdr *)swd_spindump_buffer;
- else
+ }
+ else {
hdr = (swd_hdr *)swd_buffer;
+ }
+
memset(hdr->UUID, 0x20, sizeof(hdr->UUID));
if ((UUIDstring = OSDynamicCast(OSString, getProperty(kIOPMSleepWakeUUIDKey))) != NULL ) {
DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
- while (bytesRemaining > sizeof(swd_stackshot_hdr)) {
-
- stackshotHdr = (swd_stackshot_hdr *)dstAddr;
- stackshotHdr->magic = SWD_STACKSHOTHDR_MAGIC;
- stackshotHdr->size = 0;
- bytesRemaining -= sizeof(swd_stackshot_hdr);
- dstAddr += sizeof(swd_stackshot_hdr);
+ flags = STACKSHOT_KCDATA_FORMAT|STACKSHOT_NO_IO_STATS|STACKSHOT_SAVE_KEXT_LOADINFO;
+ while (kr == KERN_SUCCESS) {
- if (isOSXWatchdog) {
- pid = -1;
- size = bytesRemaining;
- flags = STACKSHOT_SAVE_LOADINFO | STACKSHOT_SAVE_KEXT_LOADINFO;
- }
- else if (cnt == 0) {
- /*
+ if (cnt == 0) {
+ /*
* Take stackshot of all process on first sample. Size is restricted
* to SWD_INITIAL_STACK_SIZE
*/
pid = -1;
size = (bytesRemaining > initialStackSize) ? initialStackSize : bytesRemaining;
- flags = STACKSHOT_SAVE_LOADINFO | STACKSHOT_SAVE_KEXT_LOADINFO|STACKSHOT_SAVE_KERNEL_FRAMES_ONLY;
+ flags |= STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY;
}
else {
/* Take sample of kernel threads only */
pid = 0;
size = bytesRemaining;
- flags = 0;
}
- stack_snapshot_from_kernel(pid, dstAddr, size, flags, &stackshotHdr->size);
+ kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, &bytesWritten);
+ DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%x bytesWritten: %d\n",
+ kr, pid, size, flags, bytesWritten);
+ if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
+ if (pid == -1) {
+ // Insufficient buffer when trying to take stackshot of user & kernel space threads.
+ // Continue to take stackshot of just kernel threads
+ ++cnt;
+ kr = KERN_SUCCESS;
+ continue;
+ }
+ else if (totalBytes == 0) {
+ MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%x\n", kr, size, flags);
+ }
+ }
- dstAddr += stackshotHdr->size;
- bytesRemaining -= stackshotHdr->size;
+ dstAddr += bytesWritten;
+ totalBytes += bytesWritten;
+ bytesRemaining -= bytesWritten;
- DLOG("Sample: %d size: %d bytesRemaining: %d\n", cnt, stackshotHdr->size, bytesRemaining);
- if ((stackshotHdr->size == 0) || (++cnt == 10))
+ if (++cnt == 10) {
break;
+ }
IOSleep(10); // 10 ms
}
hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
- memset(hdr->cps, 0x20, sizeof(hdr->cps));
- snprintf(hdr->cps, sizeof(hdr->cps), "\ncps: %d", ((IOService*)this)->getPowerState());
+ memset(hdr->spindump_status, 0x20, sizeof(hdr->spindump_status));
code = pmTracer->getPMStatusCode();
memset(hdr->PMStatusCode, 0x20, sizeof(hdr->PMStatusCode));
snprintf(hdr->PMStatusCode, sizeof(hdr->PMStatusCode), "\nCode: %08x %08x",
hdr->spindump_offset = sizeof(swd_hdr);
swd_buffer = (void *)hdr;
+ swd_memDesc = memDesc;
DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
exit:
S_IRUSR|S_IRGRP|S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0)
{
IOLog("Failed to open the file %s\n", name);
+ swd_flags |= SWD_FILEOP_ERROR;
goto exit;
}
VATTR_INIT(&va);
if (vp->v_type != VREG ||
vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
IOLog("Bailing as this is not a regular file\n");
+ swd_flags |= SWD_FILEOP_ERROR;
goto exit;
}
VATTR_INIT(&va);
vnode_setattr(vp, &va, ctx);
- error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
- UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, vfs_context_proc(ctx));
- if (error != 0)
- IOLog("Failed to save sleep wake log. err 0x%x\n", error);
- else
- DLOG("Saved %d bytes to file %s\n",len, name);
+ if (buf != NULL) {
+ error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
+ UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, vfs_context_proc(ctx));
+ if (error != 0) {
+ IOLog("Failed to save sleep wake log. err 0x%x\n", error);
+ swd_flags |= SWD_FILEOP_ERROR;
+ }
+ else {
+ DLOG("Saved %d bytes to file %s\n",len, name);
+ }
+ }
exit:
if (vp) vnode_close(vp, FWRITE, ctx);
if (vnode_open(dstFname, (O_CREAT | FWRITE | O_NOFOLLOW),
S_IRUSR|S_IRGRP|S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0)
{
- DLOG("Failed to open the file %s\n", dstFname);
+ IOLog("Failed to open the file %s\n", dstFname);
+ swd_flags |= SWD_FILEOP_ERROR;
goto exit;
}
VATTR_INIT(&va);
/* Don't dump to non-regular files or files with links. */
if (vp->v_type != VREG ||
vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
- DLOG("Bailing as this is not a regular file\n");
+ IOLog("Bailing as this is not a regular file\n");
+ swd_flags |= SWD_FILEOP_ERROR;
goto exit;
}
VATTR_INIT(&va);
vfs_context_ucred(srcCtx), (int *) 0,
vfs_context_proc(srcCtx));
if (error) {
- DLOG("Failed to read file(numBytes:0x%llx)\n", bytesToRead);
+ IOLog("Failed to read file(numBytes:0x%llx)\n", bytesToRead);
+ swd_flags |= SWD_FILEOP_ERROR;
break;
}
vfs_context_ucred(ctx), (int *) 0,
vfs_context_proc(ctx));
if (error) {
- DLOG("Failed to write file(numBytes:0x%llx)\n", bytesToWrite);
+ IOLog("Failed to write file(numBytes:0x%llx)\n", bytesToWrite);
+ swd_flags |= SWD_FILEOP_ERROR;
break;
}
}
if (crc != newcrc) {
- swd_stackshot_hdr *shdr = (swd_stackshot_hdr *)tmpBuf;;
-
- /* Set statckshot size to 0 if crc doesn't match */
- shdr->magic = SWD_STACKSHOTHDR_MAGIC;
- shdr->size = 0;
+ /* Set stackshot size to 0 if crc doesn't match */
+ VATTR_INIT(&va);
+ VATTR_SET(&va, va_data_size, 0);
+ vnode_setattr(vp, &va, ctx);
- assert(tmpBufSize > sizeof(swd_stackshot_hdr));
- bytesToWrite = round_page(sizeof(swd_stackshot_hdr));
- vn_rdwr(UIO_WRITE, vp, (char *)tmpBuf, bytesToWrite, 0,
- UIO_SYSSPACE, IO_SYNC|IO_NODELOCKED|IO_UNIT,
- vfs_context_ucred(ctx), (int *) 0,
- vfs_context_proc(ctx));
-
- DLOG("CRC check failed. expected:0x%x actual:0x%x\n", crc, newcrc);
+ IOLog("CRC check failed. expected:0x%x actual:0x%x\n", crc, newcrc);
+ swd_flags |= SWD_DATA_CRC_ERROR;
error = EFAULT;
}
exit:
if (vp) {
error = vnode_close(vp, FWRITE, ctx);
- DLOG("vnode_close returned 0x%x\n", error);
+ DLOG("vnode_close on file %s returned 0x%x\n",dstFname, error);
}
if (ctx) vfs_context_rele(ctx);
}
-void IOPMrootDomain::checkForValidDebugData(const char *fname, vfs_context_t *ctx,
+uint32_t IOPMrootDomain::checkForValidDebugData(const char *fname, vfs_context_t *ctx,
void *tmpBuf, struct vnode **vp)
{
int rc;
uint64_t hdrOffset;
+ uint32_t error = 0;
struct vnode_attr va;
IOHibernateImageHeader *imageHdr;
VATTR_WANTED(&va, va_data_alloc);
if ((*vp)->v_type != VREG ||
vnode_getattr((*vp), &va, *ctx) || va.va_nlink != 1) {
- DMSG("sleepWakeDebugDumpFromFile: Bailing as %s is not a regular file\n", fname);
+ IOLog("sleepWakeDebugDumpFromFile: Bailing as %s is not a regular file\n", fname);
+ error = SWD_FILEOP_ERROR;
goto err;
}
vfs_context_ucred(*ctx), (int *) 0,
vfs_context_proc(*ctx));
if (rc != 0) {
- DMSG("sleepWakeDebugDumpFromFile: Failed to read header size %lu(rc=%d) from %s\n",
+ IOLog("sleepWakeDebugDumpFromFile: Failed to read header size %lu(rc=%d) from %s\n",
round_page(sizeof(IOHibernateImageHeader)), rc, fname);
+ error = SWD_FILEOP_ERROR;
goto err;
}
imageHdr = ((IOHibernateImageHeader *)tmpBuf);
if (imageHdr->signature != kIOHibernateHeaderDebugDataSignature) {
- DMSG("sleepWakeDebugDumpFromFile: File %s header has unexpected value 0x%x\n",
+ IOLog("sleepWakeDebugDumpFromFile: File %s header has unexpected value 0x%x\n",
fname, imageHdr->signature);
+ error = SWD_HDR_SIGNATURE_ERROR;
goto err;
}
/* Sleep/Wake debug header(swd_hdr) is at the beggining of the second block */
hdrOffset = imageHdr->deviceBlockSize;
if (hdrOffset + sizeof(swd_hdr) >= va.va_data_alloc) {
- DMSG("sleepWakeDebugDumpFromFile: header is crossing file size(0x%llx) in file %s\n",
+ IOLog("sleepWakeDebugDumpFromFile: header is crossing file size(0x%llx) in file %s\n",
va.va_data_alloc, fname);
+ error = SWD_HDR_SIZE_ERROR;
goto err;
}
- return;
+ return 0;
err:
if (*vp) vnode_close(*vp, FREAD, *ctx);
*vp = NULL;
- return;
+ return error;
}
void IOPMrootDomain::sleepWakeDebugDumpFromFile( )
#if HIBERNATION
int rc;
char hibernateFilename[MAXPATHLEN+1];
- char PMStatusCode[100];
void *tmpBuf;
swd_hdr *hdr = NULL;
uint32_t stacksSize, logSize;
OSNumber *failStat = NULL;
struct vnode *vp = NULL;
vfs_context_t ctx = NULL;
+ const char *stacksFname, *logFname;
IOBufferMemoryDescriptor *tmpBufDesc = NULL;
ctx = vfs_context_create(vfs_context_current());
/* First check if 'kSleepWakeStackBinFilename' has valid data */
- checkForValidDebugData(kSleepWakeStackBinFilename, &ctx, tmpBuf, &vp);
+ swd_flags |= checkForValidDebugData(kSleepWakeStackBinFilename, &ctx, tmpBuf, &vp);
if (vp == NULL) {
/* Check if the debug data is saved to hibernation file */
hibernateFilename[0] = 0;
goto exit;
}
- checkForValidDebugData(hibernateFilename, &ctx, tmpBuf, &vp);
+ swd_flags |= checkForValidDebugData(hibernateFilename, &ctx, tmpBuf, &vp);
if (vp == NULL) {
DMSG("sleepWakeDebugDumpFromFile: No valid debug data is found\n");
goto exit;
if (rc != 0) {
DMSG("sleepWakeDebugDumpFromFile: Failed to debug read header size %lu. rc=%d\n",
round_page(sizeof(swd_hdr)), rc);
+ swd_flags |= SWD_FILEOP_ERROR;
goto exit;
}
(hdr->spindump_offset > SWD_BUF_SIZE) || (hdr->spindump_size > SWD_BUF_SIZE)) {
DMSG("sleepWakeDebugDumpFromFile: Invalid data in debug header. sign:0x%x size:0x%x spindump_offset:0x%x spindump_size:0x%x\n",
hdr->signature, hdr->alloc_size, hdr->spindump_offset, hdr->spindump_size);
+ swd_flags |= SWD_BUF_SIZE_ERROR;
goto exit;
}
stacksSize = hdr->spindump_size;
stacksOffset = hdrOffset + hdr->spindump_offset;
logOffset = hdrOffset + offsetof(swd_hdr, UUID);
logSize = sizeof(swd_hdr)-offsetof(swd_hdr, UUID);
+ stacksFname = getDumpStackFilename(hdr);
+ logFname = getDumpLogFilename(hdr);
error = sleepWakeDebugCopyFile(vp, ctx, (char *)tmpBuf, tmpBufSize, stacksOffset,
- getDumpStackFilename(hdr), stacksSize, hdr->crc);
+ stacksFname, stacksSize, hdr->crc);
if (error == EFAULT) {
DMSG("sleepWakeDebugDumpFromFile: Stackshot CRC doesn't match\n");
goto exit;
}
error = sleepWakeDebugCopyFile(vp, ctx, (char *)tmpBuf, tmpBufSize, logOffset,
- getDumpLogFilename(hdr), logSize, 0);
+ logFname, logSize, 0);
if (error) {
DMSG("sleepWakeDebugDumpFromFile: Failed to write the log file(0x%x)\n", error);
goto exit;
// Write just the SleepWakeLog.dump with failure code
uint64_t fcode = 0;
const char *fname;
+ swd_hdr hdrCopy;
+ char *offset = NULL;
+ int size;
+
+ hdr = &hdrCopy;
if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
failStat = OSDynamicCast(OSNumber, getProperty(kIOPMSleepWakeFailureCodeKey));
fcode = failStat->unsigned64BitValue();
else {
fname = kAppleOSXWatchdogLogFilename;
}
- memset(PMStatusCode, 0x20, sizeof(PMStatusCode)); // Fill with spaces
- PMStatusCode[sizeof(PMStatusCode)-1] = 0xa; // And an end-of-line at the end
- snprintf(PMStatusCode, sizeof(PMStatusCode)-1, "Code: 0x%llx", fcode);
- sleepWakeDebugSaveFile(fname, PMStatusCode, sizeof(PMStatusCode));
+
+ offset = (char*)hdr+offsetof(swd_hdr, UUID);
+ size = sizeof(swd_hdr)-offsetof(swd_hdr, UUID);
+ memset(offset, 0x20, size); // Fill with spaces
+
+
+ snprintf(hdr->spindump_status, sizeof(hdr->spindump_status), "\nstatus: 0x%x", swd_flags);
+ snprintf(hdr->PMStatusCode, sizeof(hdr->PMStatusCode), "\nCode: 0x%llx", fcode);
+ snprintf(hdr->reason, sizeof(hdr->reason), "\nStackshot reason: Watchdog\n\n");
+ sleepWakeDebugSaveFile(fname, offset, size);
+
}
gRootDomain->swd_lock = 0;
errno_t error = EIO;
uint64_t bufSize = 0;
swd_hdr *hdr = NULL;
- char PMStatusCode[100];
OSNumber *failStat = NULL;
if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock))
bufSize = logBufMap->getLength();
if (bufSize <= sizeof(swd_hdr))
{
- IOLog("SleepWake log buffer contents are invalid\n");
+ IOLog("SleepWake log buffer size is invalid\n");
+ swd_flags |= SWD_BUF_SIZE_ERROR;
goto exit;
}
// Write just the SleepWakeLog.dump with failure code
uint64_t fcode = 0;
const char *sname, *lname;
- swd_stackshot_hdr shdr;
-
- /* Try writing an empty stacks file */
- shdr.magic = SWD_STACKSHOTHDR_MAGIC;
- shdr.size = 0;
-
+ swd_hdr hdrCopy;
+ /* Try writing an empty stacks file */
+ hdr = &hdrCopy;
if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
failStat = OSDynamicCast(OSNumber, getProperty(kIOPMSleepWakeFailureCodeKey));
fcode = failStat->unsigned64BitValue();
sname= kAppleOSXWatchdogStackFilename;
}
- sleepWakeDebugSaveFile(sname, (char*)(&shdr), sizeof(shdr));
- memset(PMStatusCode, 0x20, sizeof(PMStatusCode)); // Fill with spaces
- PMStatusCode[sizeof(PMStatusCode)-1] = 0xa; // And an end-of-line at the end
- snprintf(PMStatusCode, sizeof(PMStatusCode)-1, "Code: 0x%llx", fcode);
- sleepWakeDebugSaveFile(lname, PMStatusCode, sizeof(PMStatusCode));
+ sleepWakeDebugSaveFile(sname, NULL, 0);
+
+ logOffset = (char*)hdr+offsetof(swd_hdr, UUID);
+ logSize = sizeof(swd_hdr)-offsetof(swd_hdr, UUID);
+ memset(logOffset, 0x20, logSize); // Fill with spaces
+
+
+ snprintf(hdr->spindump_status, sizeof(hdr->spindump_status), "\nstatus: 0x%x", swd_flags);
+ snprintf(hdr->PMStatusCode, sizeof(hdr->PMStatusCode), "\nCode: 0x%llx", fcode);
+ snprintf(hdr->reason, sizeof(hdr->reason), "\nStackshot reason: Watchdog\n\n");
+ sleepWakeDebugSaveFile(lname, logOffset, logSize);
}
+
gRootDomain->swd_lock = 0;
}
goto exit;
}
}
- else if (len == sizeof(addr64_t)*3)
+ else if (len == sizeof(addr64_t)*3) {
PEReadNVRAMProperty(kIOSleepWakeDebugKey, data, &len);
+ }
else {
DLOG("Invalid sleepWakeDebug note length(%d)\n", len);
goto exit;
paddr = data[2];
if ( (bufSize <= sizeof(swd_hdr)) ||(bufSize > SWD_BUF_SIZE) || (crc == 0) )
{
- IOLog("SleepWake log buffer contents are invalid\n");
+ IOLog("SleepWake log buffer size is invalid\n");
+ swd_flags |= SWD_BUF_SIZE_ERROR;
return NULL;
}
if (desc == NULL)
{
IOLog("Fail to map SleepWake log buffer\n");
+ swd_flags |= SWD_INTERNAL_FAILURE;
goto exit;
}
if ( (logBufMap->getLength() <= sizeof(swd_hdr)) || (vaddr == NULL) ) {
IOLog("Fail to map SleepWake log buffer\n");
+ swd_flags |= SWD_INTERNAL_FAILURE;
goto exit;
}
hdr = (swd_hdr *)vaddr;
if (hdr->spindump_offset+hdr->spindump_size > bufSize)
{
- IOLog("SleepWake log buffer contents are invalid\n");
+ IOLog("SleepWake log header size is invalid\n");
+ swd_flags |= SWD_HDR_SIZE_ERROR;
goto exit;
}
hdr->spindump_size);
if (newcrc != crc) {
IOLog("SleepWake log buffer contents are invalid\n");
+ swd_flags |= SWD_DATA_CRC_ERROR;
goto exit;
}
void IOPMrootDomain::sleepWakeDebugTrig(bool restart)
{
+ uint32_t wdog_panic = 1;
+
+ if (restart) {
+ if (PE_parse_boot_argn("swd_panic", &wdog_panic, sizeof(wdog_panic)) &&
+ (wdog_panic == 0)) {
+ return;
+ }
+ panic("Sleep/Wake hang detected\n");
+ return;
+ }
}
void IOPMrootDomain::takeStackshot(bool restart, bool isOSXWatchdog, bool isSpinDump)