windows-nt/Source/XPSP1/NT/base/tools/kdexts2/thermal.cpp
2020-09-26 16:20:57 +08:00

1981 lines
47 KiB
C++

/*++
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,"<unknown rate>");
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 <address>\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 <address>\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 <address>\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 <address>\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;
}