/*++ Copyright (c) 1998 Microsoft Corporation Module Name: thermal Abstract: WinDbg Extension Api Author: Environment: User Mode. Revision History: --*/ #include "precomp.h" #pragma hdrstop #define TZ_LOOP 0x00000001 #define TZ_DUMP_INFO 0x00000002 #define TZ_NO_HEADER 0x80000000 PCHAR DumpPowerStateMappings[10] = { "x", "0", "1", "2", "3", "4", "5", "?", "?", "?" }; PCHAR DumpPowerActionMappings[] = { " None", " Reserved", " Sleep", "Hibernate", " Shutdown", " Reset", " Off" }; PCHAR DumpDynamicThrottleMapping[] = { " None", "Constant", " Degrade", "Adaptive", " Maximum" }; PCHAR DumpTimeInStandardForm( IN ULONG64 CurrentTime ) /*++ Routine Description: Print the Kernel's view of time into something that a user can understand Arguments: CurrentTime - Kernel's Idea of time Return Value: None --*/ { static CHAR TimeBuffer[256]; ULONG TimeIncrement; TIME_FIELDS Times; LARGE_INTEGER RunTime; TimeIncrement = GetNtDebuggerDataValue( KeTimeIncrement ); RunTime.QuadPart = UInt32x32To64(CurrentTime, TimeIncrement); RtlTimeToElapsedTimeFields( &RunTime, &Times); if (Times.Hour) { sprintf(TimeBuffer,"%3ld:%02ld:%02ld.%03lds", Times.Hour, Times.Minute, Times.Second, Times.Milliseconds); } else if (Times.Minute) { sprintf(TimeBuffer,"%02ld:%02ld.%03lds", Times.Minute, Times.Second, Times.Milliseconds); } else { sprintf(TimeBuffer,"%02ld.%03lds", Times.Second, Times.Milliseconds); } return TimeBuffer; } PCHAR DumpMicroSecondsInStandardForm( IN ULONG64 CurrentTime ) { static CHAR PerfBuffer[256]; ULONG64 FreqAddr; LARGE_INTEGER Freq; ULONG Result; ULONG64 MicroSeconds; ULONG64 MilliSeconds; ULONG64 Seconds; ULONG64 Minutes; ULONG64 Hours; ULONG64 Days; MicroSeconds = CurrentTime; MilliSeconds = MicroSeconds / 1000; MicroSeconds = MicroSeconds % 1000; Seconds = MilliSeconds / 1000; MilliSeconds = MilliSeconds % 1000; Minutes = Seconds / 60; Seconds = Seconds % 60; Hours = Minutes / 60; Minutes = Minutes % 60; Days = Hours / 24; Hours = Hours % 24; #if 0 sprintf(PerfBuffer,"%02ld:%02ld:%02ld.%03ld.%03lds", (ULONG)Hours, (ULONG)Minutes, (ULONG)Seconds, (ULONG)MilliSeconds, (ULONG)MicroSeconds ); return PerfBuffer; #endif if (Hours) { sprintf(PerfBuffer,"%02ld:%02ld:%02ld.%03ld.%03lds", (ULONG)Hours, (ULONG)Minutes, (ULONG)Seconds, (ULONG)MilliSeconds, (ULONG)MicroSeconds ); } else if (Minutes) { sprintf(PerfBuffer,"%02ld:%02ld.%03ld.%03lds", (ULONG)Minutes, (ULONG)Seconds, (ULONG)MilliSeconds, (ULONG)MicroSeconds ); } else if (Seconds) { sprintf(PerfBuffer,"%02ld.%03ld.%03lds", (ULONG)Seconds, (ULONG)MilliSeconds, (ULONG)MicroSeconds ); } else { sprintf(PerfBuffer,".%03ld.%03lds", (ULONG)MilliSeconds, (ULONG)MicroSeconds ); } return PerfBuffer; } PCHAR DumpPerformanceCounterInStandardForm( IN ULONG64 CurrentTime ) /*++ Routine Description: Print a performance counter's view of time into something that a user can understand --*/ { static CHAR PerfBuffer[256]; ULONG64 FreqAddr; LARGE_INTEGER Freq; ULONG Result; ULONG64 MicroSeconds; ULONG64 MilliSeconds; ULONG64 Seconds; ULONG64 Minutes; ULONG64 Hours; ULONG64 Days; FreqAddr = GetExpression( "nt!KdPerformanceCounterRate" ); if (!FreqAddr || !ReadMemory( FreqAddr, &Freq, sizeof(Freq), &Result) ) { sprintf(PerfBuffer,""); return PerfBuffer; } MicroSeconds = (CurrentTime * 1000000L) / Freq.LowPart; MilliSeconds = MicroSeconds / 1000; MicroSeconds = MicroSeconds % 1000; Seconds = MilliSeconds / 1000; MilliSeconds = MilliSeconds % 1000; Minutes = Seconds / 60; Seconds = Seconds % 60; Hours = Minutes / 60; Minutes = Minutes % 60; Days = Hours / 24; Hours = Hours % 24; #if 0 sprintf(PerfBuffer,"%02ld:%02ld:%02ld.%03ld.%03lds", (ULONG)Hours, (ULONG)Minutes, (ULONG)Seconds, (ULONG)MilliSeconds, (ULONG)MicroSeconds ); return PerfBuffer; #endif if (Hours) { sprintf(PerfBuffer,"%02ld:%02ld:%02ld.%03ld.%03lds", (ULONG)Hours, (ULONG)Minutes, (ULONG)Seconds, (ULONG)MilliSeconds, (ULONG)MicroSeconds ); } else if (Minutes) { sprintf(PerfBuffer,"%02ld:%02ld.%03ld.%03lds", (ULONG)Minutes, (ULONG)Seconds, (ULONG)MilliSeconds, (ULONG)MicroSeconds ); } else if (Seconds) { sprintf(PerfBuffer,"%02ld.%03ld.%03lds", (ULONG)Seconds, (ULONG)MilliSeconds, (ULONG)MicroSeconds ); } else { sprintf(PerfBuffer,".%03ld.%03lds", (ULONG)MilliSeconds, (ULONG)MicroSeconds ); } return PerfBuffer; } VOID DumpTemperatureInKelvins( IN ULONG Temperature ) /*++ Routine Description: Dumps the temperatures in Kelvins Arguments: Temperature - What to dump in Kelvins Return Value: None --*/ { dprintf(" (%d.%dK)", (Temperature / 10), (Temperature % 10) ); } VOID DumpPowerActionPolicyBrief( IN ULONG Action, IN ULONG Flags, IN ULONG EventCode ) { dprintf("%s Flags: %08lx Event: %08lx ", DumpPowerActionMappings[Action], Flags, EventCode ); if (Flags & POWER_ACTION_QUERY_ALLOWED) { dprintf(" Query"); } if (Flags & POWER_ACTION_UI_ALLOWED) { dprintf(" UI"); } if (Flags & POWER_ACTION_OVERRIDE_APPS) { dprintf(" Override"); } if (Flags & POWER_ACTION_LOCK_CONSOLE) { dprintf(" Lock"); } if (Flags & POWER_ACTION_DISABLE_WAKES) { dprintf(" NoWakes"); } if (Flags & POWER_ACTION_CRITICAL) { dprintf(" Critical"); } if (EventCode & POWER_LEVEL_USER_NOTIFY_TEXT) { dprintf(" NotifyText"); } if (EventCode & POWER_LEVEL_USER_NOTIFY_SOUND) { dprintf(" NotifySound"); } if (EventCode & POWER_LEVEL_USER_NOTIFY_EXEC) { dprintf(" NotifyExec"); } dprintf("\n"); } VOID DumpSystemPowerPolicy( IN PCHAR Pad, IN ULONG64 Address, IN ULONG Flags ) /*++ Routine Description: System Power Policy change Arguments: Return Value: --*/ { UCHAR temp; InitTypeRead(Address, nt!_SYSTEM_POWER_POLICY); if (!(Flags & TZ_NO_HEADER)) { dprintf("%sSYSTEM_POWER_POLICY (R.%d) @ 0x%08p\n", Pad, (ULONG) ReadField(Revision), Address); } temp = (UCHAR) ReadField(DynamicThrottle); if (temp > PO_THROTTLE_MAXIMUM) { temp = PO_THROTTLE_MAXIMUM; } dprintf("%s PowerButton: ", Pad); DumpPowerActionPolicyBrief( (ULONG) ReadField(PowerButton.Action), (ULONG) ReadField(PowerButton.Flags), (ULONG) ReadField(PowerButton.EventCode)); dprintf("%s SleepButton: ", Pad); DumpPowerActionPolicyBrief( (ULONG) ReadField(SleepButton.Action), (ULONG) ReadField(SleepButton.Flags), (ULONG) ReadField(SleepButton.EventCode)); dprintf("%s LidClose: ", Pad); DumpPowerActionPolicyBrief( (ULONG) ReadField(LidClose.Action), (ULONG) ReadField(LidClose.Flags), (ULONG) ReadField(LidClose.EventCode)); dprintf("%s Idle: ", Pad); DumpPowerActionPolicyBrief( (ULONG) ReadField(Idle.Action), (ULONG) ReadField(Idle.Flags), (ULONG) ReadField(Idle.EventCode)); dprintf("%s OverThrottled: ", Pad); DumpPowerActionPolicyBrief( (ULONG) ReadField(OverThrottled.Action), (ULONG) ReadField(OverThrottled.Flags), (ULONG) ReadField(OverThrottled.EventCode)); dprintf("%s IdleTimeout: %8lx IdleSensitivity: %d%%\n", Pad, (ULONG) ReadField(IdleTimeout), (ULONG) ReadField(IdleSensitivity)); dprintf("%s MinSleep: S%s MaxSleep: S%s\n", Pad, DumpPowerStateMappings[(ULONG) ReadField(MinSleep)], DumpPowerStateMappings[(ULONG) ReadField(MaxSleep)]); dprintf("%s LidOpenWake: S%s FastSleep: S%s\n", Pad, DumpPowerStateMappings[(ULONG) ReadField(LidOpenWake)], DumpPowerStateMappings[(ULONG) ReadField(ReducedLatencySleep)]); dprintf("%s WinLogonFlags: %8lx S4Timeout: %8lx\n", Pad, (ULONG) ReadField(WinLogonFlags), (ULONG) ReadField(DozeS4Timeout)); dprintf("%s VideoTimeout: %8d VideoDim: %2d\n", Pad, (ULONG) ReadField(VideoTimeout), (ULONG) ReadField(VideoDimDisplay)); dprintf("%s SpinTimeout: %8lx OptForPower: %2d\n", Pad, (ULONG) ReadField(SpindownTimeout), (ULONG) ReadField(OptimizeForPower) ); dprintf("%s FanTolerance: %4d%% ForcedThrottle: %4d%%\n", Pad, (ULONG) ReadField(FanThrottleTolerance), (ULONG) ReadField(ForcedThrottle)); dprintf("%s MinThrottle: %4d%% DyanmicThrottle: %8s (%d)\n", Pad, (ULONG) ReadField(MinThrottle), DumpDynamicThrottleMapping[temp], temp ); } DECLARE_API( popolicy ) /*++ Routine Description: Dumps the power policy Arguments: Return Value: --*/ { ULONG64 Address = 0; ULONG64 PolicyAddress; ULONG Flags = 0; ULONG Result; if (GetExpressionEx(args, &Address, &args)) { Flags = (ULONG) GetExpression(args); } if (!Address) { Address = GetExpression("nt!PopPolicy"); if (!Address) { dprintf("Could not read PopPolicy\n"); return E_INVALIDARG; } if (!ReadPointer(Address, &PolicyAddress) ) { dprintf("Could not read PopPolicy at %p\n", Address ); return E_INVALIDARG; } Address = PolicyAddress; } if (!Address) { dprintf("!popolicy [addr [flags]]\n"); return E_INVALIDARG; } if (GetFieldValue( Address, "nt!_SYSTEM_POWER_POLICY", "Revision", Result) ) { dprintf("Could not read PopPolicy at %p\n", Address ); return E_INVALIDARG; } DumpSystemPowerPolicy( "", Address, Flags ); return S_OK; } VOID DumpProcessorPowerPolicy( IN PCHAR Pad, IN ULONG64 Address, IN ULONG Flags ) /*++ Routine Description: Processor Power Policy change Arguments: Return Value: --*/ { ULONG i; ULONG count; ULONG offset; ULONG64 size; InitTypeRead(Address, nt!_PROCESSOR_POWER_POLICY); if (!(Flags & TZ_NO_HEADER)) { dprintf("%sPROCESSOR_POWER_POLICY %p (Rev .%d)\n", Pad, Address, (ULONG) ReadField(Revision) ); } dprintf( "%s DynamicThrottle: %4d PolicyCount: %8d\n", Pad, (ULONG) ReadField(DynamicThrottle), (ULONG) ReadField(PolicyCount) ); GetFieldOffset("nt!_PROCESSOR_POWER_POLICY", "Policy", &offset); Address += offset; size = GetTypeSize("nt!_PROCESSOR_POWER_POLICY_INFO"); count = (ULONG) ReadField(PolicyCount); if (count > 3) { count = 3; } // // Walk the PROCESSOR_POWER_POLICY_INFO structures // for (i = 0; i < count; i++) { InitTypeRead(Address, nt!_PROCESSOR_POWER_POLICY_INFO); dprintf( "\n%s PROCESSOR_POWER_POLICY_INFO %p\n", Pad, Address ); dprintf( "%s PromotePercent: %4d%% DemotePercent: %4d%%\n", Pad, (ULONG) ReadField( PromotePercent ), (ULONG) ReadField( DemotePercent ) ); dprintf( "%s AllowPromotion: %5s AllowDemotion: %5s\n", Pad, ( (ULONG) ReadField( AllowPromotion ) ? " TRUE" : "FALSE"), ( (ULONG) ReadField( AllowDemotion) ? " TRUE" : "FALSE") ); dprintf( "%s TimeCheck: %21s (%8p)\n", Pad, DumpMicroSecondsInStandardForm( ReadField( TimeCheck ) ), (ULONG) ReadField( TimeCheck ) ); dprintf( "%s PromoteLimit: %21s (%8p)\n", Pad, DumpMicroSecondsInStandardForm( ReadField( PromoteLimit ) ), (ULONG) ReadField( PromoteLimit ) ); dprintf( "%s DemoteLimit: %21s (%8p)\n", Pad, DumpMicroSecondsInStandardForm( ReadField( DemoteLimit ) ), (ULONG) ReadField( DemoteLimit ) ); Address += size; } } DECLARE_API( poprocpolicy ) /*++ Routine Description: Dumps the power policy Arguments: Return Value: --*/ { ULONG64 Address = 0; ULONG64 PolicyAddress; ULONG Flags = 0; ULONG Result; if (GetExpressionEx(args, &Address, &args)) { Flags = (ULONG) GetExpression(args); } if (!Address) { Address = GetExpression("nt!PopProcessorPolicy"); if (!Address) { dprintf("Could not read PopProcessorPolicy\n"); return E_INVALIDARG; } if (!ReadPointer(Address,&PolicyAddress) ) { dprintf("Could not read PopProcessorPolicy at %p\n", Address ); return E_INVALIDARG; } Address = PolicyAddress; } if (!Address) { dprintf("!poprocpolicy [addr [flags]]\n"); return E_INVALIDARG; } if (GetFieldValue( Address,"PROCESSOR_POWER_POLICY", "Revision", Result) ) { dprintf("Could not read PopProcessorPolicy at %p\n", Address ); return E_INVALIDARG; } DumpProcessorPowerPolicy( "", Address, Flags ); return S_OK; } VOID DumpProcessorPowerState( IN PCHAR Pad, IN ULONG64 Address, IN ULONG Flags ) /*++ Routine Description: Processor Power State dump Arguments: Return Value: --*/ { ULONG time; ULONG temp; CHAR FunctionName[256]; ULONG64 Offset; InitTypeRead(Address, nt!_PROCESSOR_POWER_STATE); if (!(Flags & TZ_NO_HEADER)) { dprintf("%sPROCESSOR_POWER_STATE %p\n", Pad, Address ); } dprintf( "%s IdleState: %16p IdleHandlers: %16p\n", Pad, ReadField(IdleState), ReadField(IdleHandlers) ); dprintf( "%s C1 Idle Transitions: %8lx C1 Idle Time: %17s\n", Pad, (ULONG) ReadField( TotalIdleTransitions[0] ), DumpPerformanceCounterInStandardForm( ReadField( TotalIdleStateTime[0] ) ) ); dprintf( "%s C2 Idle Transitions: %8lx C2 Idle Time: %17s\n", Pad, (ULONG) ReadField( TotalIdleTransitions[1] ), DumpPerformanceCounterInStandardForm( ReadField( TotalIdleStateTime[1] ) ) ); dprintf( "%s C3 Idle Transitions: %8lx C3 Idle Time: %17s\n\n", Pad, (ULONG) ReadField( TotalIdleTransitions[2] ), DumpPerformanceCounterInStandardForm( ReadField( TotalIdleStateTime[2] ) ) ); dprintf( "%s DebugDelta: %16I64x LastCheck: %17s\n", Pad, ReadField(DebugDelta), DumpPerformanceCounterInStandardForm( ReadField( LastCheck ) ) ); dprintf( "%s DebugCount: %8lx IdleTime.Start: %17s\n", Pad, (ULONG) ReadField(DebugCount), DumpPerformanceCounterInStandardForm( ReadField( IdleTimes.StartTime ) ) ); dprintf( "%s PromotionCheck: %8lx IdleTime.End: %17s\n", Pad, (ULONG) ReadField(PromotionCheck ), DumpPerformanceCounterInStandardForm( ReadField( IdleTimes.EndTime ) ) ); dprintf( "%s IdleTime1: %8lx Idle0LastTime: %17s\n", Pad, (ULONG) ReadField(IdleTime1), DumpTimeInStandardForm( ReadField( Idle0LastTime ) ) ); dprintf( "%s IdleTime2: %8lx LastSystTime: %17s\n", Pad, (ULONG) ReadField(IdleTime2), DumpTimeInStandardForm( ReadField( LastSysTime ) ) ); dprintf( "%s CurrentThrottle: %4d%% Idle0KernelTimeLimit: %15s\n", Pad, (ULONG) ReadField(CurrentThrottle), DumpTimeInStandardForm( ReadField( Idle0KernelTimeLimit ) ) ); dprintf( "%s CurrentThrottleIndex: %4d ThermalThrottleLimit: %4d%%\n", Pad, (ULONG) ReadField(CurrentThrottleIndex), (ULONG) ReadField(ThermalThrottleLimit) ); dprintf( "%s KneeThrottleIndex: %4d ThermalThrottleIndex: %4d\n", Pad, (ULONG) ReadField(KneeThrottleIndex), (ULONG) ReadField(ThermalThrottleIndex) ); dprintf( "%s ThrottleLimitIndex: %4d Flags: %8x\n", Pad, (ULONG) ReadField(ThrottleLimitIndex), (ULONG) ReadField(Flags) ); dprintf( "%s PerfStates: %8p PerfStatesCount: %4d\n", Pad, ReadField(PerfStates), (ULONG) ReadField(PerfStatesCount) ); dprintf( "%s ProcessorMinThrottle: %4d%% ProcessorMaxThrottle: %4d%%\n", Pad, (ULONG) ReadField(ProcessorMinThrottle), (ULONG) ReadField(ProcessorMaxThrottle) ); dprintf( "%s PromotionCount: %8d DemotionCount: %8d\n", Pad, (ULONG) ReadField( PromotionCount ), (ULONG) ReadField( DemotionCount ) ); dprintf( "%s ErrorCount: %8d RetryCount: %8d\n", Pad, (ULONG) ReadField(ErrorCount), (ULONG) ReadField(RetryCount) ); dprintf( "%s LastBusyPercentage: %4d%% LastC3Percentage: %4d%%\n", Pad, (ULONG) ReadField( LastBusyPercentage ), (ULONG) ReadField( LastC3Percentage ) ); dprintf( "%s LastAdjustedBusyPercent: %4d%%\n", Pad, (ULONG) ReadField(LastAdjustedBusyPercentage) ); dprintf("\n"); GetSymbol(ReadField(IdleFunction), FunctionName, &Offset); dprintf( "%s IdleFunction: %50s\n", Pad, FunctionName ); GetSymbol(ReadField(PerfSetThrottle), FunctionName, &Offset); dprintf( "%s PerfSetThrottle: %50s\n", Pad, FunctionName ); dprintf( "%s PreviousC3StateTime: %21s (%16p)\n", Pad, DumpPerformanceCounterInStandardForm( ReadField( PreviousC3StateTime ) ), ReadField( PreviousC3StateTime ) ); dprintf( "%s PerfSystemTime: %21s (%8x)\n", Pad, DumpTimeInStandardForm( ReadField(PerfSystemTime) ), ReadField( PerfSystemTime ) ); dprintf( "%s PerfIdleTime: %21s (%8x)\n", Pad, DumpTimeInStandardForm( ReadField(PerfIdleTime) ), ReadField( PerfIdleTime ) ); dprintf( "%s PerfTickCount: %21s (%8x)\n", Pad, DumpTimeInStandardForm( ReadField(PerfTickCount) ), ReadField( PerfTickCount ) ); // // At this point, go look at the corresponding PRCB to see what the // kernel and user times are // GetFieldOffset("nt!_KPRCB", "PowerState", &temp); Address -= temp; InitTypeRead( Address, _KPRCB ); time = (ULONG) ReadField(UserTime) + (ULONG) ReadField(KernelTime); dprintf( "%s CurrentSystemTime: %21s (%8x)\n", Pad, DumpTimeInStandardForm( time ), time ); // // Read the Idle Thread to see what the current idle thread time is // Address = ReadField( IdleThread ); InitTypeRead( Address, _KTHREAD ); time = (ULONG) ReadField(KernelTime); dprintf( "%s CurrentIdleTime: %21s (%8x)\n", Pad, DumpTimeInStandardForm( time ), time ); } DECLARE_API( poproc ) /*++ Routine Description: Dumps the Processor Power State Arguments: Return Value: --*/ { ULONG64 Address = 0; ULONG64 Pkprcb; ULONG Flags = 0; ULONG processor; ULONG64 Result; // // Get address and flags // if (GetExpressionEx(args, &Address, &args)) { Flags = (ULONG) GetExpression(args); } if (Address == 0) { HRESULT Hr; INIT_API(); GetCurrentProcessor(Client, &processor, NULL); Hr = g_ExtData->ReadProcessorSystemData(processor, DEBUG_DATA_KPRCB_OFFSET, &Pkprcb, sizeof(Pkprcb), NULL); if (Hr != S_OK) { dprintf("Cannot get PRCB address\n"); } else { InitTypeRead(Pkprcb,nt!_KPRCB); Address = ReadField(PowerState); if (!Address) { dprintf("Unable to get PowerState from the PRCB at %p",Pkprcb); dprintf("poproc
\n"); Hr = E_INVALIDARG; } } if (Hr != S_OK) { return Hr; } } if (GetFieldValue( Address, "PROCESSOR_POWER_STATE", "IdleTime1", Result) ) { dprintf("Could not read PROCESSOR_POWER_STATE at %08p\n", Address ); return E_INVALIDARG; } // // Dump the Trigger Information // DumpProcessorPowerState("", Address, Flags ); return S_OK; } VOID DumpPowerCapabilities( IN PCHAR Pad, IN ULONG64 Address, IN ULONG Flags ) /*++ Routine Description: Dumps the power capabilities Arguments: Return Value: --*/ { InitTypeRead(Address, nt!SYSTEM_POWER_CAPABILITIES); if (!(Flags & TZ_NO_HEADER)) { dprintf("%sPopCapabilities @ 0x%08p\n", Pad, Address ); } dprintf("%s Misc Supported Features: ", Pad); if ((ULONG) ReadField(PowerButtonPresent)) { dprintf(" PwrButton"); } if ((ULONG) ReadField(SleepButtonPresent)) { dprintf(" SlpButton"); } if ((ULONG) ReadField(LidPresent)) { dprintf(" Lid"); } if ((ULONG) ReadField(SystemS1)) { dprintf(" S1"); } if ((ULONG) ReadField(SystemS2)) { dprintf(" S2"); } if ((ULONG) ReadField(SystemS3)) { dprintf(" S3"); } if ((ULONG) ReadField(SystemS4)) { dprintf(" S4"); } if ((ULONG) ReadField(SystemS5)) { dprintf(" S5"); } if ((ULONG) ReadField(HiberFilePresent)) { dprintf(" HiberFile"); } if ((ULONG) ReadField(FullWake)) { dprintf(" FullWake"); } if ((ULONG) ReadField(VideoDimPresent)) { dprintf(" VideoDim"); } dprintf("\n"); dprintf("%s Processor Features: ", Pad); if ((ULONG) ReadField(ThermalControl)) { dprintf(" Thermal"); } if ((ULONG) ReadField(ProcessorThrottle)) { dprintf(" Throttle (MinThrottle = %d%%, Scale = %d%%)", (ULONG) ReadField(ProcessorMinThrottle), (ULONG) ReadField(ProcessorThrottleScale)); } dprintf("\n"); dprintf("%s Disk Features: ", Pad ); if ((ULONG) ReadField(DiskSpinDown)) { dprintf(" SpinDown"); } dprintf("\n"); dprintf("%s Battery Features: ", Pad); if ((ULONG) ReadField(SystemBatteriesPresent)) { dprintf(" BatteriesPresent"); } if ((ULONG) ReadField(BatteriesAreShortTerm)) { dprintf(" ShortTerm"); } dprintf("\n"); if ((ULONG) ReadField(SystemBatteriesPresent)) { dprintf("%s Battery 0 - Capacity: %8lx Granularity: %8lx\n", Pad, (ULONG) ReadField(BatteryScale[0].Capacity), (ULONG) ReadField(BatteryScale[0].Granularity) ); dprintf("%s Battery 1 - Capacity: %8lx Granularity: %8lx\n", Pad, (ULONG) ReadField(BatteryScale[1].Capacity), (ULONG) ReadField(BatteryScale[1].Granularity) ); dprintf("%s Battery 2 - Capacity: %8lx Granularity: %8lx\n", Pad, (ULONG) ReadField(BatteryScale[2].Capacity), (ULONG) ReadField(BatteryScale[2].Granularity) ); } dprintf("%s Wake Caps\n", Pad); dprintf("%s Ac OnLine Wake: S%s\n", Pad, DumpPowerStateMappings[(ULONG) ReadField(AcOnLineWake)]); dprintf("%s Soft Lid Wake: S%s\n", Pad, DumpPowerStateMappings[(ULONG) ReadField(SoftLidWake)]); dprintf("%s RTC Wake: S%s\n", Pad, DumpPowerStateMappings[(ULONG) ReadField(RtcWake)]); dprintf("%s Min Device Wake: S%s\n", Pad, DumpPowerStateMappings[(ULONG) ReadField(MinDeviceWakeState)]); dprintf("%s Default Wake: S%s\n", Pad, DumpPowerStateMappings[(ULONG) ReadField(DefaultLowLatencyWake)]); } DECLARE_API( pocaps ) /*++ Routine Description: Dumps the power capabilities Arguments: Return Value: --*/ { ULONG64 Address = 0; ULONG Flags = 0; ULONG Result; if (GetExpressionEx(args, &Address, &args)) { Flags = (ULONG) GetExpression(args); } if (!Address) { Address = GetExpression("nt!PopCapabilities"); if (!Address) { dprintf("Could not read PopCapabilities\n"); return E_INVALIDARG; } } if (!Address) { dprintf("!pocaps [addr [flags]]\n"); return E_INVALIDARG; } if (GetFieldValue(Address, "nt!SYSTEM_POWER_CAPABILITIES", "PowerButtonPresent", Result) ) { dprintf("Could not read PopCapabilities at %08p\n", Address ); return E_INVALIDARG; } DumpPowerCapabilities( "", Address, Flags ); return S_OK; } VOID DumpPopActionTrigger( IN PCHAR Pad, IN ULONG64 Address, IN ULONG Flags ) /*++ --*/ { ULONG Type, PopFlags; InitTypeRead(Address, nt!_POP_ACTION_TRIGGER); // // Header line // if (!(Flags & TZ_NO_HEADER)) { dprintf("%sPOP_ACTION_TRIGGER @ 0x%08p\n", Pad, Address ); } dprintf("%s Type: ", Pad); switch(Type = (ULONG) ReadField(Type)) { case PolicyDeviceSystemButton: dprintf(" SystemButton"); break; case PolicyDeviceThermalZone: dprintf(" ThermalZone"); break; case PolicyDeviceBattery: dprintf(" Battery"); break; case PolicyInitiatePowerActionAPI: dprintf(" InitActionAPI"); break; case PolicySetPowerStateAPI: dprintf(" SetStateAPI"); break; case PolicyImmediateDozeS4: dprintf(" DozeS4"); break; case PolicySystemIdle: dprintf(" SystemIdle"); break; default: dprintf(" Unknown"); break; } dprintf(" Flags: %02x%02x%02x%02x", (ULONG) ReadField(Spare[2]), (ULONG) ReadField(Spare[1]), (ULONG) ReadField(Spare[0]), (PopFlags = (ULONG) ReadField(Flags))); if (PopFlags & PO_TRG_USER) { dprintf(" UserAction"); } if (PopFlags & PO_TRG_SYSTEM) { dprintf(" SystemAction"); } if (PopFlags & PO_TRG_SYNC) { dprintf(" Sync"); } if (PopFlags & PO_TRG_SET) { dprintf(" Set"); } dprintf("\n"); if (Type != PolicyDeviceBattery) { dprintf("%s Wait Trigger: %08p\n", Pad, ReadField(Wait )); } else { dprintf("%s BatteryLevel: %08lx\n", Pad, (ULONG) ReadField(Battery.Level )); } } DECLARE_API( potrigger ) /*++ Routine Description: Dumps a Pop Action Trigger Arguments: Return Value: --*/ { ULONG64 Address = 0; ULONG Flags = 0; ULONG Result; // // Get address and flags // if (GetExpressionEx(args, &Address, &args)) { Flags = (ULONG) GetExpression(args); } if (Address == 0) { dprintf("potrigger
\n"); return E_INVALIDARG; } if (GetFieldValue(Address, "nt!_POP_ACTION_TRIGGER", "Type", Result) ) { dprintf("Could not read POP_ACTION_TRIGGER at %08p\n", Address ); return E_INVALIDARG; } // // Dump the Trigger Information // DumpPopActionTrigger("", Address, Flags ); return S_OK; } VOID DumpThermalZoneInformation( IN PCHAR Pad, IN ULONG64 Address, IN ULONG Flags ) /*++ Routine Description: Displays the thermal zone information structure Arguments: Return Value: --*/ { ULONG i, Count; InitTypeRead(Address, nt!_THERMAL_INFORMATION); // // Header line // if (!(Flags & TZ_NO_HEADER)) { dprintf("%sThermalInfo @ 0x%08p\n", Pad, Address ); } // // First line // dprintf("%s Stamp: %08lx Constant1: %08lx Constant2: %08lx\n", Pad, (ULONG) ReadField(ThermalStamp), (ULONG) ReadField(ThermalConstant1), (ULONG) ReadField(ThermalConstant2)); // // Second Line // dprintf("%s Affinity: %08lx Period: %08lx ActiveCnt: %08lx\n", Pad, (ULONG) ReadField(Processors), (ULONG) ReadField(SamplingPeriod), (ULONG) ReadField(ActiveTripPointCount )); // // Temperatures // dprintf("%s Current Temperature: %08lx", Pad, (ULONG) ReadField(CurrentTemperature )); DumpTemperatureInKelvins((ULONG) ReadField(CurrentTemperature)); dprintf("\n"); dprintf("%s Passive TripPoint Temperature: %08lx", Pad, (ULONG) ReadField(PassiveTripPoint )); DumpTemperatureInKelvins((ULONG) ReadField(PassiveTripPoint)); dprintf("\n"); // // Active trip points // Count = (ULONG) ReadField(ActiveTripPointCount); for (i = 0; i < Count; i++) { CHAR Buff[40]; ULONG Act; sprintf(Buff, "ActiveTripPoint[%d]", i); dprintf("%s Active TripPoint Temperature %d: %08lx", Pad, i, (Act = (ULONG) GetShortField(0, Buff, 0))); DumpTemperatureInKelvins(Act); dprintf("\n"); } // // Dump critical temperatures // dprintf("%s Critical TripPoint Temperature: %08lx", Pad, (ULONG) ReadField(CriticalTripPoint )); DumpTemperatureInKelvins((ULONG) ReadField(CriticalTripPoint)); dprintf("\n"); } DECLARE_API( tzinfo ) /*++ Routine Description: Dumps the thermal zone information structure Arguments: Return Value: --*/ { // THERMAL_INFORMATION ThermalInfo; ULONG64 Address = 0; ULONG Flags = 0; ULONG Result; // // Get address and flags // if (GetExpressionEx(args, &Address, &args)) { Flags = (ULONG) GetExpression(args); } if (Address == 0) { dprintf("tzinfo
\n"); return E_INVALIDARG; } if (GetFieldValue(Address, "nt!_THERMAL_INFORMATION", "ThermalStamp", Result) ) { dprintf("Could not read THERMAL_INFO at %08p\n", Address ); return E_INVALIDARG; } // // Dump the thermal zone information // DumpThermalZoneInformation("", Address, Flags ); return S_OK; } VOID DumpThermalZone( IN ULONG Count, IN PCHAR Pad, IN ULONG64 Address, IN ULONG Flags ) /*++ Routine Description: Dumps a thermal zone --*/ { ULONG ThFlags, Off1, Off2, LastTemp; InitTypeRead(Address, NT!_POP_THERMAL_ZONE); // // Header line // if (!(Flags & TZ_NO_HEADER)) { dprintf("%s%d - ThermalZone @ 0x%08p\n", Pad, Count, Address ); } // // First line // dprintf("%s State: ",Pad); switch ((ULONG) ReadField(State)) { case 1: dprintf(" Read"); break; case 2: dprintf("Set Mode"); break; case 3: dprintf(" Active"); break; default:dprintf("No State"); break; } dprintf(" Flags: %08lx", (ThFlags = (ULONG) ReadField(Flags))); if (ThFlags & PO_TZ_THROTTLING) { dprintf(" Throttling"); } if (ThFlags & PO_TZ_CLEANUP) { dprintf(" CleanUp"); } dprintf("\n"); // // Second Line // dprintf("%s Mode: ", Pad ); switch((ULONG) ReadField(Mode)) { case 0: dprintf(" Active"); break; case 1: dprintf(" Passive"); break; default: dprintf(" Invalid"); break; } dprintf(" PendingMode: "); switch((ULONG) ReadField(PendingMode)) { case 0: dprintf(" Active"); break; case 1: dprintf(" Passive"); break; default: dprintf(" Invalid"); break; } dprintf("\n"); dprintf("%s ActivePoint: %08lx PendingTrp: %08lx\n", Pad, (ULONG) ReadField(ActivePoint), (ULONG) ReadField(PendingActivePoint )); dprintf("%s SampleRate: %08lx LastTime: %016I64x\n", Pad, (ULONG) ReadField(SampleRate), ReadField(LastTime )); GetFieldOffset("NT!_POP_THERMAL_ZONE", "PassiveTimer", &Off1); GetFieldOffset("NT!_POP_THERMAL_ZONE", "PassiveDpc", &Off2); dprintf("%s Timer: %08lx Dpc: %08lx\n", Pad, Address + Off1, Address + Off2); GetFieldOffset("NT!_POP_THERMAL_ZONE", "OverThrottled", &Off1); dprintf("%s OverThrottled: %08lx Irp: %08p\n", Pad, Address + Off1, ReadField(Irp )); dprintf("%s Throttle: %08lx LastTemp: %08lx", Pad, (ULONG) ReadField(Throttle), (LastTemp = (ULONG) ReadField(LastTemp ))); DumpTemperatureInKelvins( LastTemp ); dprintf("\n"); GetFieldOffset("NT!_POP_THERMAL_ZONE", "Info", &Off1); dprintf("%s Thermal Info: %08lx\n", Pad, Address + Off1); if (Flags & TZ_DUMP_INFO) { CHAR buffer[80]; // // Increase the buffer // sprintf(buffer," %s", Pad ); // // Dump the thermal zone // DumpThermalZoneInformation( buffer, (Address + Off1), (Flags | TZ_NO_HEADER) ); } } DECLARE_API( tz ) /*++ Routine Description: Arguments: args - Return Value: None --*/ { ULONG64 Address = 0; ULONG Count = 0; ULONG64 EndAddress = 0, Flink; ULONG Flags = 0; ULONG Result; // // Get address and flags // if (GetExpressionEx(args, &Address, &args)) { Flags = (ULONG) GetExpression(args); } if (Address == 0) { Address = GetExpression("nt!PopThermal"); if (!Address) { dprintf("Could not read PopThermal\n"); return E_INVALIDARG; } if (GetFieldValue(Address, "nt!_LIST_ENTRY", "Flink", Flink) ) { dprintf("Could not read PopThermal at %08p\n", Address ); return E_INVALIDARG; } if (Flink == Address) { dprintf("No Thermal Zones\n"); return E_INVALIDARG; } Flags |= TZ_LOOP; EndAddress = Address; Address = Flink; } else { EndAddress = Address; } // // Now read the proper thermal zone // if (GetFieldValue(Address, "nt!_LIST_ENTRY", "Flink", Flink) ) { dprintf("Could not read LIST_ENTRY at %08p\n", Address ); return E_INVALIDARG; } // // Do we stop looping? // if (!Flags & TZ_LOOP) { EndAddress = Flink; } do { // // Read the thermal zone // Try both names for backward compatibility // if (GetFieldValue(Address, "NT!_POP_THERMAL_ZONE", "Link.Flink", Flink) && GetFieldValue(Address, "NT!POP_THERMAL_ZONE", "Link.Flink", Flink)) { dprintf("Could not read THERMAL_ZONE at %08p\n", Address ); return E_INVALIDARG; } // // Dump the zone // DumpThermalZone( Count, "", Address, Flags ); // // Check for Control C // if (CheckControlC()) { return E_INVALIDARG; } // // Next // Address = Flink; Count++; } while (Address != EndAddress ); return S_OK; } VOID DumpPopIdleHandler( IN ULONG64 Address, IN ULONG Flags ) /*++ Routine Description: Arguments: Return Value: --*/ { CHAR FunctionName[256]; ULONG64 Offset; if (InitTypeRead(Address,nt!_POP_IDLE_HANDLER)) { // If the new type name fails, use the old one InitTypeRead(Address,nt!POP_IDLE_HANDLER); } dprintf("PopIdleHandle[%d] - POP_IDLE_HANDLER %p\n",(ULONG)ReadField(State),Address); dprintf(" State: %8d PromoteCount: %8d\n", (ULONG)ReadField(State), (ULONG)ReadField(PromoteCount) ); dprintf(" DemotePercent: %8d%% PromotePercent: %8d%%\n", (ULONG)ReadField(DemotePercent), (ULONG)ReadField(PromotePercent) ); dprintf(" Demote: %8d Promote: %8d\n", (ULONG)ReadField(Demote), (ULONG)ReadField(Promote) ); dprintf("\n"); GetSymbol(ReadField(IdleFunction), FunctionName, &Offset); dprintf(" Function: %27s (%p)\n", FunctionName, ReadField(IdleFunction) ); dprintf(" Latency: %27s (%8x)\n", DumpPerformanceCounterInStandardForm( (ULONG)ReadField(Latency) ), (ULONG)ReadField(Latency) ); dprintf(" TimeCheck: %27s (%8x)\n", DumpPerformanceCounterInStandardForm( (ULONG)ReadField(TimeCheck) ), (ULONG)ReadField(TimeCheck) ); dprintf(" PromoteLimit: %27s (%8x)\n", DumpPerformanceCounterInStandardForm( (ULONG)ReadField(PromoteLimit) ), (ULONG)ReadField(PromoteLimit) ); dprintf(" DemoteLimit: %27s (%8x)\n", DumpPerformanceCounterInStandardForm( (ULONG)ReadField(DemoteLimit) ), (ULONG) ReadField(DemoteLimit) ); dprintf("\n"); } DECLARE_API( poidle ) /*++ Routine Description: Arguments: Return Value: --*/ { ULONG64 Address = 0; ULONG64 Pkprcb; ULONG64 PowerState; ULONG64 Size; ULONG Loop = 3; ULONG Flags = 0; ULONG processor = 0; // // Get address and flags // if (GetExpressionEx(args, &Address, &args)) { Flags = (ULONG) GetExpression(args); } if (Address == 0) { HRESULT Hr; INIT_API(); GetCurrentProcessor(Client, &processor, NULL); Hr = g_ExtData->ReadProcessorSystemData(processor, DEBUG_DATA_KPRCB_OFFSET, &Pkprcb, sizeof(Pkprcb), NULL); if (Hr != S_OK) { dprintf("Cannot get PRCB address\n"); } else { InitTypeRead(Pkprcb,nt!_KPRCB); PowerState = ReadField(PowerState); if (!PowerState) { dprintf("Unable to get PowerState from the PRCB at %p",Pkprcb); dprintf("poproc
\n"); Hr = E_INVALIDARG; } } if (Hr != S_OK){ return Hr; } if (GetFieldValue( PowerState, "PROCESSOR_POWER_STATE", "IdleHandlers", Address) ) { dprintf("Could not read PROCESSOR_POWER_STATE at %p\n", PowerState ); return E_INVALIDARG; } Loop = 3; } // // We will need to know how large the structure is.. // Size = GetTypeSize("nt!_POP_IDLE_HANDLER"); if (!Size) { Size = GetTypeSize("nt!POP_IDLE_HANDLER"); } do { DumpPopIdleHandler( Address, Flags ); Address += Size; if (CheckControlC() || !Loop) { break; } Loop--; } while ( Loop ); return S_OK; } VOID DumpProcessorPerfState( IN ULONG64 Address, IN ULONG Flags ) /*++ Routine Description: Arguments: Return Value: --*/ { ULONG64 Value = 0; InitTypeRead(Address,nt!PROCESSOR_PERF_STATE); dprintf( " Power: %4dmW", (ULONG)ReadField(Power) ); Value = ReadField(Flags); if (Value) { dprintf(" NonLinear\n"); } else { dprintf(" Linear\n"); } dprintf( " Frequency: %8d%% MinCapacity: %8d%%\n", (ULONG)ReadField(PercentFrequency), (ULONG)ReadField(MinCapacity) ); dprintf( " IncreaseLevel: %8d%% DecreaseLevel: %8d%%\n", (ULONG)ReadField(IncreaseLevel), (ULONG)ReadField(DecreaseLevel) ); dprintf( " IncreaseCount: %8x DecreaseCount: %8x\n", (ULONG)ReadField(IncreaseCount), (ULONG)ReadField(DecreaseCount) ); dprintf( " PerformanceTime: %21s (%8x)\n", DumpPerformanceCounterInStandardForm( ReadField(PerformanceTime) ), ReadField(PerformanceTime) ); dprintf( " IncreaseTime: %21s (%8x)\n", DumpTimeInStandardForm( (ULONG) ReadField(IncreaseTime) ), ReadField(IncreaseTime) ); dprintf( " DecreaseTime: %21s (%8x)\n", DumpTimeInStandardForm( (ULONG) ReadField(DecreaseTime) ), ReadField(DecreaseTime) ); } DECLARE_API( poperf ) /*++ Routine Description: Arguments: Return Value: --*/ { ULONG64 Address = 0; ULONG64 Count = 1; ULONG64 Index; ULONG64 PolicyAddress; ULONG64 Size = 0; ULONG Flags = 0; ULONG Processor; ULONG Prcb; // // Get address and flags // if (GetExpressionEx(args, &Address, &args)) { Flags = (ULONG) GetExpression(args); } if (Address == 0) { HRESULT Hr; INIT_API(); // // Fetch them from the current processor's prcb // GetCurrentProcessor(Client, &Processor, NULL); Hr = g_ExtData->ReadProcessorSystemData( Processor, DEBUG_DATA_KPRCB_OFFSET, &Address, sizeof(Address), NULL ); if (Hr != S_OK) { dprintf("Unable to get PRCB address\n"); return Hr; } InitTypeRead(Address,nt!_KPRCB); PolicyAddress = ReadField(PowerState.PerfStates); Count = ReadField(PowerState.PerfStatesCount); // // Remember what's the address we will use // Address = PolicyAddress; dprintf("Prcb.PowerState.PerfStates - %p (%d Levels)\n", Address, (ULONG) Count ); } else { dprintf("PROCESSOR_PERF_STATE - %p\n",Address); } // // We will need to know how large the structure is.. // Size = GetTypeSize("nt!PROCESSOR_PERF_STATE"); // // Dump all the states // for (Index = 0; Index < Count; Index++, Address += Size) { DumpProcessorPerfState( Address, Flags ); if (CheckControlC()) { break; } } // // Done // return S_OK; } DECLARE_API( whattime ) { ULONG64 Address = 0; // // Get address and flags // GetExpressionEx(args, &Address, &args); dprintf( "%d Ticks in Standard Time: %s\n", (ULONG) Address, DumpTimeInStandardForm( (ULONG) Address ) ); return S_OK; } DECLARE_API( whatperftime ) { ULONG64 Address = 0; // // Get address and flags // GetExpressionEx(args, &Address, &args); dprintf( "%ld Performance Counter in Standard Time: %s\n", (ULONG) Address, DumpPerformanceCounterInStandardForm( Address ) ); return S_OK; }