PpmSnapPerformanceAccumulation
UINT8 __stdcall PpmSnapPerformanceAccumulation(
_KPRCB *Prcb,
UINT8 Reset,
UINT8 Remote,
UINT8 SnapPmc,
_PROC_PERF_CHECK_SNAP *Snap){
unsigned __int64 *a5;
UINT8 v6;
UINT64 v9;
INT64 v10;
__int64 v11;
__int64 v12;
volatile unsigned __int64 v13;
UINT64 v14;
signed __int64 IdleTimeEntry;
signed __int64 v16;
UINT8 result;
INT64 v18;
__int64 v19;
__int64 v20;
volatile unsigned __int64 QpcBias;
unsigned __int64 v22;
unsigned __int64 v23;
unsigned __int64 v24;
unsigned __int64 CyclesLast;
__int64 v26;
unsigned __int64 IdleTimeTotal;
unsigned __int64 CyclesActive;
unsigned __int64 v29;
__int64 v30;
unsigned __int64 v31;
signed __int64 v32;
signed __int64 v33;
__int64 v34;
__int64 v35;
__int64 v36;
__int64 v37;
__int64 v38;
unsigned __int64 v39;
__int64 v40;
int v41;
unsigned __int64 v42;
__int64 v43;
__int64 v44;
unsigned __int64 v45;
signed __int64 v46;
__int64 v47;
bool v48;
__int64 v49;
__int64 v50;
__int64 v51;
__int64 v52;
unsigned __int64 v53;
__int64 v54;
int v55;
unsigned __int64 v56;
__int64 v57;
__int64 v58;
unsigned __int64 v59;
signed __int64 v60;
__int64 v61;
UINT64 v62;
unsigned __int64 v63;
__int64 v64;
__int64 v65;
__int64 v66;
__int64 v67;
__int64 v68;
unsigned __int64 v69;
__int64 v70;
int v71;
unsigned __int64 v72;
__int64 v73;
__int64 v74;
unsigned __int64 v75;
signed __int64 v76;
__int64 v77;
__int64 v78;
__int64 v79;
__int64 v80;
__int64 v81;
unsigned __int64 v82;
__int64 v83;
int v84;
unsigned __int64 v85;
__int64 v86;
__int64 v87;
unsigned __int64 v88;
signed __int64 v89;
__int64 v90;
UINT64 v91;
signed __int32 v92[8];
UINT8 v93;
UINT8 v94;
UINT64 FromFrequency;
UINT64 v96;
__int64 v97;
__int128 v98;
__int64 v99;
a5 = 0i64;
v93 = SnapPmc;
v94 = Reset;
v99 = 0i64;
v6 = SnapPmc;
v97 = 0i64;
v9 = 0i64;
v98 = 0i64;
if( !Remote )
{
_disable();
v18 = HalpPerformanceCounter;
if( *(_DWORD *)(HalpPerformanceCounter + 228) == 5 )
{
v96 = 10000000i64;
if( !HalpTimerReferencePage )
{
if( *(_DWORD *)(HalpPerformanceCounter + 220) == 64 )
{
HalpTimerGetInternalData((_KDPC *)HalpPerformanceCounter, (PVOID)Reset, (PVOID)Remote, (PVOID)SnapPmc);
v65 = (*(__int64(__fastcall **)(__int64))(v18 + 112))(v64);
v66 = *(_QWORD *)(v18 + 208);
*(_QWORD *)&Reset = v65;
}
else
{
do
{
v66 = *(_QWORD *)(v18 + 208);
do
{
v67 = *(_QWORD *)(v18 + 200);
HalpTimerGetInternalData((_KDPC *)v18, (PVOID)Reset, (PVOID)Remote, (PVOID)SnapPmc);
v69 = (*(__int64(__fastcall **)(__int64))(v18 + 112))(v68);
_InterlockedOr(v92, 0);
v70 = *(_QWORD *)(v18 + 200);
}
while( v67 != v70 );
}
while( v66 != *(_QWORD *)(v18 + 208) );
v71 = *(_DWORD *)(v18 + 220);
v72 = v67 ^ v69;
if( _bittest64((const __int64 *)&v72, (unsigned __int8)(v71 - 1)) )
{
v73 = 1i64;
if( v71 == 64 )
v74 = -1i64;
else
v74 = (1i64 << v71) - 1;
if( v71 != 64 )
v73 = 1i64 << v71;
v75 = v67 & v74;
*(_QWORD *)&Reset = v69 | v67 ^ v75;
if( v69 < v75 )
*(_QWORD *)&Reset = v73 + Reset;
_InterlockedCompareExchange64((volatile signed __int64 *)(v18 + 200), Reset, v76);
}
else
{
if( v71 == 64 )
v77 = -1i64;
else
v77 = (1i64 << v71) - 1;
*(_QWORD *)&Reset = v69 | v67 & ~v77;
}
}
v14 = HalpTimerScaleCounter(v66 + Reset, *(_QWORD *)(v18 + 192), 0x989680ui64);
goto LABEL_21;
}
if( (*(_DWORD *)(HalpPerformanceCounter + 224) & 0x10000) != 0 )
v19 = *(_QWORD *)(HalpPerformanceCounter + 72)
+ *(_DWORD *)(HalpPerformanceCounter + 80) * KeGetPcr()->Prcb.Number;
else
v19 = *(_QWORD *)(HalpPerformanceCounter + 72);
v20 = (*(__int64(__fastcall **)(__int64))(HalpPerformanceCounter + 112))(v19);
QpcBias = KUSER_SHARED_DATA.QpcBias;
*(_OWORD *)(&Reset - 8) = (unsigned __int64)v20
* (unsigned __int128)*((unsigned __int64 *)HalpTimerReferencePage + 1);
}
else
{
v48 = *(_DWORD *)(HalpPerformanceCounter + 220) == 64;
v96 = *(_QWORD *)(HalpPerformanceCounter + 192);
if( v48 )
{
HalpTimerGetInternalData((_KDPC *)HalpPerformanceCounter, (PVOID)Reset, (PVOID)Remote, (PVOID)SnapPmc);
v79 = (*(__int64(__fastcall **)(__int64))(v18 + 112))(v78);
QpcBias = *(_QWORD *)(v18 + 208);
*(_QWORD *)&Reset = v79;
}
else
{
do
{
QpcBias = *(_QWORD *)(v18 + 208);
do
{
v80 = *(_QWORD *)(v18 + 200);
HalpTimerGetInternalData((_KDPC *)v18, (PVOID)Reset, (PVOID)Remote, (PVOID)SnapPmc);
v82 = (*(__int64(__fastcall **)(__int64))(v18 + 112))(v81);
_InterlockedOr(v92, 0);
v83 = *(_QWORD *)(v18 + 200);
}
while( v80 != v83 );
}
while( QpcBias != *(_QWORD *)(v18 + 208) );
v84 = *(_DWORD *)(v18 + 220);
v85 = v80 ^ v82;
if( _bittest64((const __int64 *)&v85, (unsigned __int8)(v84 - 1)) )
{
v86 = 1i64;
if( v84 == 64 )
v87 = -1i64;
else
v87 = (1i64 << v84) - 1;
if( v84 != 64 )
v86 = 1i64 << v84;
v88 = v80 & v87;
*(_QWORD *)&Reset = v82 | v80 ^ v88;
if( v82 < v88 )
*(_QWORD *)&Reset = v86 + Reset;
_InterlockedCompareExchange64((volatile signed __int64 *)(v18 + 200), Reset, v89);
}
else
{
if( v84 == 64 )
v90 = -1i64;
else
v90 = (1i64 << v84) - 1;
*(_QWORD *)&Reset = v82 | v80 & ~v90;
}
}
}
v14 = Reset + QpcBias;
LABEL_21:
if( v18 != HalpOriginalPerformanceCounter && HalpOriginalPerformanceCounter )
{
v91 = *(_QWORD *)(HalpOriginalPerformanceCounter + 192);
if( *(_DWORD *)(HalpOriginalPerformanceCounter + 228) == 5 )
v91 = 10000000i64;
v14 = HalpTimerScaleCounter(v14, v96, v91);
}
v22 = __rdtsc();
if( (Prcb->FeatureBits & 0x8000000000i64) != 0 )
v23 = __readmsr(0xDB2u);
else
v23 = 0i64;
v24 = v14 - Prcb->PowerState.PerfFeedback.LastUpdateTime;
_InterlockedExchangeAdd64(&Prcb->PowerState.PerfFeedback.UnaccountedTime, v24);
if( (Prcb->FeatureBits & 0x8000000000i64) != 0 )
Prcb->PowerState.PerfFeedback.StallTime += PpmConvertTime(
v24,
v22 - Prcb->PowerState.PerfFeedback.CyclesLast,
v23 - Prcb->PowerState.PerfFeedback.StallCyclesLast);
CyclesLast = Prcb->PowerState.PerfFeedback.CyclesLast;
Prcb->PowerState.PerfFeedback.LastUpdateTime = v14;
if( v22 > CyclesLast )
Prcb->PowerState.PerfFeedback.CyclesActive += v22 - CyclesLast;
Prcb->PowerState.PerfFeedback.CyclesLast = v22;
a5 = 0i64;
if( (Prcb->FeatureBits & 0x8000000000i64) != 0 )
Prcb->PowerState.PerfFeedback.StallCyclesLast = v23;
v6 = v93;
goto LABEL_31;
}
v10 = HalpPerformanceCounter;
if( *(_DWORD *)(HalpPerformanceCounter + 228) != 5 )
{
v48 = *(_DWORD *)(HalpPerformanceCounter + 220) == 64;
FromFrequency = *(_QWORD *)(HalpPerformanceCounter + 192);
if( v48 )
{
HalpTimerGetInternalData((_KDPC *)HalpPerformanceCounter, (PVOID)Reset, (PVOID)Remote, (PVOID)SnapPmc);
v50 = (*(__int64(__fastcall **)(__int64))(v10 + 112))(v49);
v13 = *(_QWORD *)(v10 + 208);
*(_QWORD *)&Reset = v50;
}
else
{
do
{
v13 = *(_QWORD *)(v10 + 208);
do
{
v51 = *(_QWORD *)(v10 + 200);
HalpTimerGetInternalData((_KDPC *)v10, (PVOID)Reset, (PVOID)Remote, (PVOID)SnapPmc);
v53 = (*(__int64(__fastcall **)(__int64))(v10 + 112))(v52);
_InterlockedOr(v92, 0);
v54 = *(_QWORD *)(v10 + 200);
}
while( v51 != v54 );
}
while( v13 != *(_QWORD *)(v10 + 208) );
v55 = *(_DWORD *)(v10 + 220);
v56 = v51 ^ v53;
if( _bittest64((const __int64 *)&v56, (unsigned __int8)(v55 - 1)) )
{
v57 = 1i64;
if( v55 == 64 )
v58 = -1i64;
else
v58 = (1i64 << v55) - 1;
if( v55 != 64 )
v57 = 1i64 << v55;
v59 = v51 & v58;
*(_QWORD *)&Reset = v53 | v51 ^ v59;
if( v53 < v59 )
*(_QWORD *)&Reset = v57 + Reset;
_InterlockedCompareExchange64((volatile signed __int64 *)(v10 + 200), Reset, v60);
a5 = 0i64;
}
else
{
if( v55 == 64 )
v61 = -1i64;
else
v61 = (1i64 << v55) - 1;
*(_QWORD *)&Reset = v53 | v51 & ~v61;
a5 = 0i64;
}
}
goto LABEL_7;
}
FromFrequency = 10000000i64;
if( HalpTimerReferencePage )
{
if( (*(_DWORD *)(HalpPerformanceCounter + 224) & 0x10000) != 0 )
v11 = *(_QWORD *)(HalpPerformanceCounter + 72)
+ *(_DWORD *)(HalpPerformanceCounter + 80) * KeGetPcr()->Prcb.Number;
else
v11 = *(_QWORD *)(HalpPerformanceCounter + 72);
v12 = (*(__int64(__fastcall **)(__int64))(HalpPerformanceCounter + 112))(v11);
v13 = KUSER_SHARED_DATA.QpcBias;
*(_OWORD *)(&Reset - 8) = (unsigned __int64)v12
* (unsigned __int128)*((unsigned __int64 *)HalpTimerReferencePage + 1);
LABEL_7:
v14 = Reset + v13;
goto LABEL_8;
}
if( *(_DWORD *)(HalpPerformanceCounter + 220) == 64 )
{
HalpTimerGetInternalData((_KDPC *)HalpPerformanceCounter, (PVOID)Reset, (PVOID)Remote, (PVOID)SnapPmc);
v35 = (*(__int64(__fastcall **)(__int64))(v10 + 112))(v34);
v36 = *(_QWORD *)(v10 + 208);
*(_QWORD *)&Reset = v35;
}
else
{
do
{
v36 = *(_QWORD *)(v10 + 208);
do
{
v37 = *(_QWORD *)(v10 + 200);
HalpTimerGetInternalData((_KDPC *)v10, (PVOID)Reset, (PVOID)Remote, (PVOID)SnapPmc);
v39 = (*(__int64(__fastcall **)(__int64))(v10 + 112))(v38);
_InterlockedOr(v92, 0);
v40 = *(_QWORD *)(v10 + 200);
}
while( v37 != v40 );
}
while( v36 != *(_QWORD *)(v10 + 208) );
v41 = *(_DWORD *)(v10 + 220);
v42 = v37 ^ v39;
if( _bittest64((const __int64 *)&v42, (unsigned __int8)(v41 - 1)) )
{
v43 = 1i64;
if( v41 == 64 )
v44 = -1i64;
else
v44 = (1i64 << v41) - 1;
if( v41 != 64 )
v43 = 1i64 << v41;
v45 = v37 & v44;
*(_QWORD *)&Reset = v39 | v37 ^ v45;
if( v39 < v45 )
*(_QWORD *)&Reset = v43 + Reset;
_InterlockedCompareExchange64((volatile signed __int64 *)(v10 + 200), Reset, v46);
a5 = 0i64;
}
else
{
if( v41 == 64 )
v47 = -1i64;
else
v47 = (1i64 << v41) - 1;
*(_QWORD *)&Reset = v39 | v37 & ~v47;
a5 = 0i64;
}
}
v14 = HalpTimerScaleCounter(v36 + Reset, *(_QWORD *)(v10 + 192), 0x989680ui64);
LABEL_8:
if( v10 != HalpOriginalPerformanceCounter && HalpOriginalPerformanceCounter )
{
v62 = *(_QWORD *)(HalpOriginalPerformanceCounter + 192);
if( *(_DWORD *)(HalpOriginalPerformanceCounter + 228) == 5 )
v62 = 10000000i64;
v14 = HalpTimerScaleCounter(v14, FromFrequency, v62);
}
_m_prefetchw((const void *)&Prcb->PowerState.IdleTimeEntry);
IdleTimeEntry = Prcb->PowerState.IdleTimeEntry;
do
{
v16 = IdleTimeEntry;
IdleTimeEntry = _InterlockedCompareExchange64(
(volatile signed __int64 *)&Prcb->PowerState.IdleTimeEntry,
IdleTimeEntry,
IdleTimeEntry);
}
while( v16 != IdleTimeEntry );
v9 = IdleTimeEntry;
if( IdleTimeEntry )
{
if( Prcb->PowerState.Hypervisor == ProcHypervisorHvCounters )
{
v63 = Prcb->StatisticsPage[DWORD2(xmmword_140CED0E0)];
v9 = v63 >> 1;
if( (v63 & 1) == 0 )
v9 = 0i64;
}
}
if( !v9 )
return 0;
LABEL_31:
memset(Snap, 0i64, sizeof(_PROC_PERF_CHECK_SNAP));
Snap->CyclesAffinitized = Prcb->AffinitizedCycles + Prcb->CycleTime;
Snap->TaggedThreadCycles[0] = Prcb->TaggedCycles[0];
Snap->TaggedThreadCycles[1] = Prcb->TaggedCycles[1];
Snap->TaggedThreadCycles[2] = Prcb->TaggedCycles[2];
if( !Remote )
_enable();
if( Prcb->PowerState.Hypervisor == ProcHypervisorHvCounters )
a5 = (unsigned __int64 *)&v98;
result = PpmUpdatePerformanceFeedback(Prcb, v94, Remote, 0, (INT64)a5);
if( result )
{
if( v6 && *(&stru_140C23628 + 764) )
{
LOBYTE(v26) = 1;
(*(&stru_140C23628 + 764))(Prcb->Number, Remote, v26);
}
if( a5 )
{
v29 = *a5;
IdleTimeTotal = a5[1];
CyclesActive = a5[2];
v30 = v97;
}
else
{
IdleTimeTotal = Prcb->PowerState.IdleTimeTotal;
CyclesActive = Prcb->PowerState.PerfFeedback.CyclesActive;
v29 = v9;
if( v14 > v9 )
v29 = v14;
v30 = v9;
}
if( Prcb->PowerState.PerfFeedback.Counters[0] )
{
v31 = Prcb->PowerState.PerfFeedback.ScaledTime[0];
}
else if( Prcb->PowerState.PerfFeedback.Counters[1] )
{
v31 = Prcb->PowerState.PerfFeedback.ScaledTime[1];
}
else
{
v31 = 100 * Prcb->PowerState.PerfFeedback.UnscaledTime;
}
Snap->FrequencyScaledActive = v31;
if( Prcb->PowerState.PerfFeedback.Counters[1] )
v31 = Prcb->PowerState.PerfFeedback.ScaledTime[1];
Snap->PerformanceScaledActive = v31;
Snap->PerformanceScaledKernelActive = Prcb->PowerState.PerfFeedback.PerformanceScaledKernelTime;
Snap->Stall = Prcb->PowerState.PerfFeedback.StallTime;
Snap->ResponsivenessEvents = Prcb->DpcData[0].DpcCount;
if( Remote )
{
_m_prefetchw((const void *)&Prcb->PowerState.IdleTimeEntry);
v32 = Prcb->PowerState.IdleTimeEntry;
do
{
v33 = v32;
v32 = _InterlockedCompareExchange64((volatile signed __int64 *)&Prcb->PowerState.IdleTimeEntry, v32, v32);
}
while( v33 != v32 );
if( v32 )
{
if( Prcb->PowerState.Hypervisor == ProcHypervisorHvCounters )
{
v32 = Prcb->StatisticsPage[DWORD2(xmmword_140CED0E0)] >> 1;
if( (Prcb->StatisticsPage[DWORD2(xmmword_140CED0E0)] & 1) == 0 )
v32 = 0i64;
}
}
if( v9 != v32 )
return 0;
if( !a5 )
IdleTimeTotal += v29 - v30;
}
else if( !a5 )
{
IdleTimeTotal += Prcb->PowerState.IdleTimeLast;
}
Snap->Time = v29;
result = 1;
Snap->CyclesActive = CyclesActive;
Snap->Active = v29 - IdleTimeTotal;
}
return result;
}Referenced by:
PpmCapturePerformanceDistributionCallback
PpmCheckSnapAllDeliveredPerformance
PpmGetThroughputInfoCallback
PpmPerfSnapDeliveredPerformance
PpmResetPerfTimes