1648 lines
40 KiB
C
1648 lines
40 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
i64prfle.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
|
||
|
This module implements the IA64 Hal Profiling using the performance
|
||
|
counters within the core of the first IA64 Processor Merced, aka Itanium.
|
||
|
This module is appropriate for all machines based on microprocessors using
|
||
|
the Merced core.
|
||
|
|
||
|
With the information known at this development time, this module tries to
|
||
|
consider the future IA64 processor cores by encapsulating the differences
|
||
|
in specific micro-architecture data structures.
|
||
|
|
||
|
Furthermore, with the implementation of the new NT ACPI Processor driver, this
|
||
|
implementation will certainly change in the coming months.
|
||
|
|
||
|
N.B. - This module assumes that all processors in a multiprocessor
|
||
|
system are running the microprocessor at the same clock speed.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Thierry Fevrier 08-Feb-2000
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Kernel mode only.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "halp.h"
|
||
|
|
||
|
//
|
||
|
// Assumptions for the current implementation - 02/08/2000 :
|
||
|
// These assumptions will be re-evaluated and worked out if required.
|
||
|
//
|
||
|
// - Respect and satisfy as much possible the Profiling Sources interface
|
||
|
// already defined by NT and HAL.
|
||
|
//
|
||
|
// - All processors in a multiprocessor system are running the microprocessor
|
||
|
// at the same invariant clock speed.
|
||
|
//
|
||
|
// - All processors are configured with the same set of profiling counters.
|
||
|
// XXTF - 04/01/2000 - This assumption is being re-worked and will disappear.
|
||
|
//
|
||
|
// - Profiling is based on the processor monitored events and if possible
|
||
|
// on derived events.
|
||
|
//
|
||
|
// - A monitored event can only be enabled on one performance counter at a time.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// IA64 performance counters defintions:
|
||
|
// - event counters
|
||
|
// - EARS
|
||
|
// - BTBs
|
||
|
// - ...
|
||
|
//
|
||
|
|
||
|
#include "ia64prof.h"
|
||
|
#if defined(_MCKINLEY_)
|
||
|
#include "mckinley.h"
|
||
|
#else // Default IA64 - Merced
|
||
|
#include "merced.h"
|
||
|
#endif //
|
||
|
|
||
|
extern ULONGLONG HalpITCFrequency;
|
||
|
extern HALP_PROFILE_MAPPING HalpProfileMapping[];
|
||
|
|
||
|
#define HalpDisactivateProfileSource( _ProfileSource ) ((_ProfileSource) = ProfileIA64Maximum)
|
||
|
#define HalpIsProfileSourceActive( _ProfileSource ) ((_ProfileSource) != ProfileIA64Maximum)
|
||
|
#define HalpIsProfileMappingInvalid( _ProfileMapping ) (!(_ProfileMapping) || ((_ProfileMapping)->Supported == FALSE))
|
||
|
|
||
|
VOID
|
||
|
HalpEnableProfileCounting (
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function enables the profile counters to increment.
|
||
|
This function is the counterpart of HalpDisableProfileCounting().
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG Data, ClearStatusMask;
|
||
|
|
||
|
//
|
||
|
// Clear PMC0.fr - bit 0.
|
||
|
// Clear PMCO,1,2,3 OverFlow Bits.
|
||
|
//
|
||
|
|
||
|
ClearStatusMask = 0xFFFFFFFFFFFFFF0E; // XXTF - FIXFIX - Merced specific.
|
||
|
Data = HalpReadPerfMonCnfgReg0();
|
||
|
Data &= ClearStatusMask;
|
||
|
HalpWritePerfMonCnfgReg0(Data);
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpEnableProfileCounting()
|
||
|
|
||
|
VOID
|
||
|
HalpDisableProfileCounting (
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function disables the profile counters to increment.
|
||
|
This function is the counterpart of HalpEnableProfileCounting().
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG Data, SetFreezeMask;
|
||
|
|
||
|
SetFreezeMask = 0x1;
|
||
|
Data = HalpReadPerfMonCnfgReg0();
|
||
|
Data |= SetFreezeMask;
|
||
|
HalpWritePerfMonCnfgReg0(Data);
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpDisableProfileCounting()
|
||
|
|
||
|
VOID
|
||
|
HalpSetInitialProfileState(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function is called at HalInitSystem - phase 0 time to set
|
||
|
the initial state of processor and profiling os subsystem with
|
||
|
regards to the profiling functionality.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
// HalpProfilingRunning = 0;
|
||
|
|
||
|
HalpDisableProfileCounting();
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpSetInitialProfileState()
|
||
|
|
||
|
VOID
|
||
|
HalpSetProfileCounterInterval (
|
||
|
IN ULONG Counter,
|
||
|
IN LONGLONG NextCount
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function preloads the specified counter with a count value
|
||
|
of 2^IMPL_BITS - NextCount.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
NextCount - Supplies the value to preload in the monitor.
|
||
|
An external interruption will be generated after NextCount.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Note:
|
||
|
|
||
|
IMPL_BITS is defined by PAL_PERF_MON_INFO.PAL_WIDTH.
|
||
|
|
||
|
ToDo:
|
||
|
|
||
|
IMPL_BITS is hardcoded to 32.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
ULONGLONG Count;
|
||
|
|
||
|
#define MAXIMUM_COUNT 4294967296 // 2 ** 32 for Merced. XXTF - FIXFIX - Merced specific.
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
if (NextCount > MAXIMUM_COUNT) {
|
||
|
Count = 0;
|
||
|
} else {
|
||
|
Count = MAXIMUM_COUNT - NextCount;
|
||
|
}
|
||
|
|
||
|
HalpWritePerfMonDataReg( Counter, Count );
|
||
|
|
||
|
#undef MAXIMUM_COUNT
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpSetProfileCounterInterval()
|
||
|
|
||
|
VOID
|
||
|
HalpSetProfileCounterPrivilegeLevelMask(
|
||
|
IN ULONG Counter,
|
||
|
IN ULONG Mask
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function set the profile counter privilege level mask.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
Mask - Supplies the privilege level mask to program the PMC with.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, plmMask;
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
plmMask = Mask & 0xF;
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
data &= ~0xF;
|
||
|
data |= plmMask;
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpSetProfileCounterPrivilegeLevelMask()
|
||
|
|
||
|
VOID
|
||
|
HalpEnableProfileCounterOverflowInterrupt (
|
||
|
IN ULONG Counter
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function enables the delivery of an overflow interrupt for
|
||
|
the specified profile counter.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, mask;
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
mask = 1<<5;
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
data |= mask;
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpEnableProfileCounterOverflowInterrupt()
|
||
|
|
||
|
VOID
|
||
|
HalpDisableProfileCounterOverflowInterrupt (
|
||
|
IN ULONG Counter
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function disables the delivery of an overflow interrupt for
|
||
|
the specified profile counter.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, mask;
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
mask = 1<<5;
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
data &= ~mask;
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpDisableProfileCounterOverflowInterrupt()
|
||
|
|
||
|
VOID
|
||
|
HalpEnableProfileCounterPrivilegeMonitor(
|
||
|
IN ULONG Counter
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function enables the profile counter as privileged monitor.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, pm;
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
pm = 1<<6;
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
data |= pm;
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpEnableProfileCounterPrivilegeMonitor()
|
||
|
|
||
|
VOID
|
||
|
HalpDisableProfileCounterPrivilegeMonitor(
|
||
|
IN ULONG Counter
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function disables the profile counter as privileged monitor.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, pm;
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
pm = 1<<6;
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
data &= ~pm;
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpDisableProfileCounterPrivilegeMonitor()
|
||
|
|
||
|
VOID
|
||
|
HalpSetProfileCounterEvent(
|
||
|
IN ULONG Counter,
|
||
|
IN ULONG Event
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
The function specifies the monitor event for the profile counter.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
Event - Supplies the monitor event code.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, es;
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
es = (Event & 0x7F) << 8;
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
data &= ~(0x7F << 8);
|
||
|
data |= es;
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpSetProfileCounterEvent()
|
||
|
|
||
|
VOID
|
||
|
HalpSetProfileCounterUmask(
|
||
|
IN ULONG Counter,
|
||
|
IN ULONG Umask
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function sets the event specific umask value for the profile
|
||
|
counter.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
Umask - Supplies the event specific umask value.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, um;
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
um = (Umask & 0xF) << 16;
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
data &= ~(0xF << 16);
|
||
|
data |= um;
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpSetProfileCounterUmask()
|
||
|
|
||
|
VOID
|
||
|
HalpSetProfileCounterThreshold(
|
||
|
IN ULONG Counter,
|
||
|
IN ULONG Threshold
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function sets the profile counter threshold.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
Threshold - Supplies the desired threshold.
|
||
|
This is related to multi-occurences events.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, reset, th;
|
||
|
|
||
|
switch( Counter ) {
|
||
|
case 4:
|
||
|
case 5:
|
||
|
Threshold &= 0x7;
|
||
|
reset = ~(0x7 << 20);
|
||
|
break;
|
||
|
|
||
|
case 6:
|
||
|
case 7:
|
||
|
Threshold &= 0x3;
|
||
|
reset = ~(0x3 << 20);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
th = Threshold << 20;
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
data &= reset;
|
||
|
data |= th;
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpSetProfileCounterThreshold()
|
||
|
|
||
|
VOID
|
||
|
HalpSetProfileCounterInstructionSetMask(
|
||
|
IN ULONG Counter,
|
||
|
IN ULONG Mask
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function sets the instruction set mask for the profile counter.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Counter - Supplies the performance counter register number.
|
||
|
|
||
|
Mask - Supplies the instruction set mask.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, ismMask;
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
ismMask = (Mask & 0x3) << 24;
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
data &= ~(0x3 << 24);
|
||
|
data |= ismMask;
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpSetProfileCounterInstructionSetMask()
|
||
|
|
||
|
VOID
|
||
|
HalpSetProfileCounterConfiguration(
|
||
|
IN ULONG Counter,
|
||
|
IN ULONG PrivilegeMask,
|
||
|
IN ULONG EnableOverflowInterrupt,
|
||
|
IN ULONG EnablePrivilegeMonitor,
|
||
|
IN ULONG Event,
|
||
|
IN ULONG Umask,
|
||
|
IN ULONG Threshold,
|
||
|
IN ULONG InstructionSetMask
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Function Description:
|
||
|
|
||
|
This function sets the profile counter with the specified parameters.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IN ULONG Counter -
|
||
|
|
||
|
IN ULONG PrivilegeMask -
|
||
|
|
||
|
IN ULONG EnableOverflowInterrupt -
|
||
|
|
||
|
IN ULONG EnablePrivilegeMonitor -
|
||
|
|
||
|
IN ULONG Event -
|
||
|
|
||
|
IN ULONG Umask -
|
||
|
|
||
|
IN ULONG Threshold -
|
||
|
|
||
|
IN ULONG InstructionSetMask -
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
VOID
|
||
|
|
||
|
Algorithm:
|
||
|
|
||
|
ToBeSpecified
|
||
|
|
||
|
In/Out Conditions:
|
||
|
|
||
|
ToBeSpecified
|
||
|
|
||
|
Globals Referenced:
|
||
|
|
||
|
ToBeSpecified
|
||
|
|
||
|
Exception Conditions:
|
||
|
|
||
|
ToBeSpecified
|
||
|
|
||
|
MP Conditions:
|
||
|
|
||
|
ToBeSpecified
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
This function is a kind of combo of the different profile counter APIs.
|
||
|
It was created to provide speed.
|
||
|
|
||
|
ToDo List:
|
||
|
|
||
|
- Setting the threshold is not yet supported.
|
||
|
|
||
|
Modification History:
|
||
|
|
||
|
3/16/2000 TF Initial version
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG data, plmMask, ismMask, es, um, th;
|
||
|
|
||
|
// if ( (Counter < 4) || (Counter > 7) ) return;
|
||
|
|
||
|
plmMask = (PrivilegeMask & 0xF);
|
||
|
es = (Event & 0x7F) << 8;
|
||
|
um = (Umask & 0xF) << 16;
|
||
|
// XXTF - ToBeDone - Threshold not supported yet.
|
||
|
ismMask = (InstructionSetMask & 0x3) << 24;
|
||
|
|
||
|
data = HalpReadPerfMonCnfgReg( Counter );
|
||
|
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalpSetProfileCounterConfiguration: Counter = %ld Read = 0x%I64x\n", Counter, data ));
|
||
|
|
||
|
data &= ~( (0x3 << 24) | (0xF << 16) | (0x7F << 8) | 0xF );
|
||
|
data |= ( plmMask | es | um | ismMask );
|
||
|
data = EnableOverflowInterrupt ? (data | (1<<5)) : (data & ~(1<<5));
|
||
|
data = EnablePrivilegeMonitor ? (data | (1<<6)) : (data & ~(1<<6));
|
||
|
|
||
|
HalpWritePerfMonCnfgReg( Counter, data );
|
||
|
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalpSetProfileCounterConfiguration: Counter = %ld Written = 0x%I64x\n", Counter, data ));
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpSetProfileCounterConfiguration()
|
||
|
|
||
|
NTSTATUS
|
||
|
HalpProgramProfileMapping(
|
||
|
PHALP_PROFILE_MAPPING ProfileMapping,
|
||
|
KPROFILE_SOURCE ProfileSource
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function enables the profiling configuration for the event defined by the
|
||
|
specified Profile Mapping entry.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ProfileMapping - Supplies the Profile Mapping entry.
|
||
|
|
||
|
ProfileSource - Supplies the Profile Source corresponding to the Profile Mapping entry.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_SUCCESS -
|
||
|
|
||
|
STATUS_INVALID_PARAMETER -
|
||
|
|
||
|
STATUS_UNSUCESSFUL -
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS status;
|
||
|
ULONG sourceMask;
|
||
|
|
||
|
if ( ! ProfileMapping ) {
|
||
|
return STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
// XXTF - ToBeDone - Derived Event
|
||
|
|
||
|
sourceMask = ProfileMapping->ProfileSourceMask;
|
||
|
if ( (sourceMask & PMCD_MASK_4) && !HalpIsProfileSourceActive( HalpProfileSource4 ) ) {
|
||
|
|
||
|
HalpSetProfileCounterConfiguration( 4,
|
||
|
PMC_PLM_ALL,
|
||
|
PMC_ENABLE_OVERFLOW_INTERRUPT,
|
||
|
PMC_ENABLE_PRIVILEGE_MONITOR,
|
||
|
ProfileMapping->Event,
|
||
|
0, // Umask
|
||
|
0, // Threshold
|
||
|
PMC_ISM_ALL
|
||
|
);
|
||
|
|
||
|
HalpSetProfileCounterInterval( 4, ProfileMapping->Interval );
|
||
|
|
||
|
HalpProfileSource4 = ProfileSource;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
if ( (sourceMask & PMCD_MASK_5) && !HalpIsProfileSourceActive( HalpProfileSource5 ) ) {
|
||
|
|
||
|
HalpSetProfileCounterConfiguration( 5,
|
||
|
PMC_PLM_ALL,
|
||
|
PMC_ENABLE_OVERFLOW_INTERRUPT,
|
||
|
PMC_ENABLE_PRIVILEGE_MONITOR,
|
||
|
ProfileMapping->Event,
|
||
|
0, // Umask
|
||
|
0, // Threshold
|
||
|
PMC_ISM_ALL
|
||
|
);
|
||
|
|
||
|
HalpSetProfileCounterInterval( 5, ProfileMapping->Interval );
|
||
|
|
||
|
HalpProfileSource5 = ProfileSource;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
if ( (sourceMask & PMCD_MASK_6) && !HalpIsProfileSourceActive( HalpProfileSource6 ) ) {
|
||
|
|
||
|
HalpSetProfileCounterConfiguration( 6,
|
||
|
PMC_PLM_ALL,
|
||
|
PMC_ENABLE_OVERFLOW_INTERRUPT,
|
||
|
PMC_ENABLE_PRIVILEGE_MONITOR,
|
||
|
ProfileMapping->Event,
|
||
|
0, // Umask
|
||
|
0, // Threshold
|
||
|
PMC_ISM_ALL
|
||
|
);
|
||
|
|
||
|
HalpSetProfileCounterInterval( 6, ProfileMapping->Interval );
|
||
|
|
||
|
HalpProfileSource6 = ProfileSource;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
if ( (sourceMask & PMCD_MASK_7) && !HalpIsProfileSourceActive( HalpProfileSource7 ) ) {
|
||
|
|
||
|
HalpSetProfileCounterConfiguration( 7,
|
||
|
PMC_PLM_ALL,
|
||
|
PMC_ENABLE_OVERFLOW_INTERRUPT,
|
||
|
PMC_ENABLE_PRIVILEGE_MONITOR,
|
||
|
ProfileMapping->Event,
|
||
|
0, // Umask
|
||
|
0, // Threshold
|
||
|
PMC_ISM_ALL
|
||
|
);
|
||
|
|
||
|
HalpSetProfileCounterInterval( 7, ProfileMapping->Interval );
|
||
|
|
||
|
HalpProfileSource7 = ProfileSource;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
} // HalpProgramProfileMapping()
|
||
|
|
||
|
ULONG_PTR
|
||
|
HalpSetProfileInterruptHandler(
|
||
|
IN ULONG_PTR ProfileInterruptHandler
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function registers a per-processor Profiling Interrupt Handler.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ProfileInterruptHandler - Interrupt Handler.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
(ULONG_PTR)STATUS_SUCCESS - Successful registration.
|
||
|
|
||
|
(ULONG_PTR)STATUS_ALREADY_COMMITTED - Cannot register an handler if profiling events are running.
|
||
|
|
||
|
(ULONG_PTR)STATUS_PORT_ALREADY_SET - An Profiling Interrupt Handler was already registred - not imposed currently.
|
||
|
|
||
|
Note:
|
||
|
|
||
|
IT IS THE RESPONSIBILITY OF THE CALLER OF THIS ROUTINE TO ENSURE
|
||
|
THAT NO PAGE FAULTS WILL OCCUR DURING EXECUTION OF THE PROVIDED
|
||
|
FUNCTION OR ACCESS TO THE PROVIDED CONTEXT.
|
||
|
A MINIMUM OF FUNCTION POINTER CHECKING WAS DONE IN HalSetSystemInformation PROCESSING.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// If profiling is already running, we do not allow the handler registration.
|
||
|
//
|
||
|
// This imposes that:
|
||
|
//
|
||
|
// - if the default HAL profiling is running or a profiling with a registered interrupt
|
||
|
// handler is running, we cannot register an interrupt handler.
|
||
|
// In the last case, all the profiling events have to be stopped before a possible
|
||
|
// registration.
|
||
|
//
|
||
|
// It should be also noticed that there is no ownership of profiling monitors implemented.
|
||
|
// Meaning that if profiling is started, the registred handler will get the interrupts
|
||
|
// generated by ALL the running monitor events if they are programmed to generate interrupts.
|
||
|
//
|
||
|
|
||
|
if ( HalpProfilingRunning ) {
|
||
|
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalpSetProfileInterruptHandler: Profiling already running\n" ));
|
||
|
return((ULONG_PTR)(ULONG)(STATUS_ALREADY_COMMITTED));
|
||
|
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
//
|
||
|
// Thierry - 03/2000. ToBeVerified.
|
||
|
//
|
||
|
// In case, no profiling was started, there is currently no restriction in registering
|
||
|
// another handler if one was already registered.
|
||
|
//
|
||
|
|
||
|
if ( HalpProfillingInterruptHandler ) {
|
||
|
return((ULONG_PTR)(ULONG)(STATUS_PORT_ALREADY_SET));
|
||
|
}
|
||
|
|
||
|
#endif // 0
|
||
|
|
||
|
HalpProfilingInterruptHandler = (ULONGLONG)ProfileInterruptHandler;
|
||
|
return((ULONG_PTR)(ULONG)(STATUS_SUCCESS));
|
||
|
|
||
|
} // HalpSetProfileInterruptHandler()
|
||
|
|
||
|
VOID
|
||
|
HalpProfileInterrupt(
|
||
|
IN PKINTERRUPT_ROUTINE Interrupt,
|
||
|
IN PKTRAP_FRAME TrapFrame
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Default PROFILE_VECTOR Interrupt Handler.
|
||
|
This function is executed as the result of an interrupt from the
|
||
|
internal microprocessor performance counters. The interrupt
|
||
|
may be used to signal the completion of a profile event.
|
||
|
If profiling is current active, the function determines if the
|
||
|
profile interval has expired and if so dispatches to the standard
|
||
|
system routine to update the system profile time. If profiling
|
||
|
is not active then returns.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
TrapFrame - Trap frame address.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Call registered per-processor Profiling Interrupt handler if it exists.
|
||
|
// We will return immediately before doing any default profiling interrupt handling.
|
||
|
//
|
||
|
// XXTF - ToBeVerified - This functionality has to be verified before
|
||
|
// final check-in.
|
||
|
//
|
||
|
|
||
|
if ( HalpProfilingInterruptHandler ) {
|
||
|
(*((PHAL_PROFILE_INTERRUPT_HANDLER)HalpProfilingInterruptHandler))( TrapFrame );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Handle interrupt if profiling is enabled.
|
||
|
//
|
||
|
|
||
|
if ( HalpProfilingRunning ) {
|
||
|
|
||
|
//
|
||
|
// Process every PMC/PMD pair overflow.
|
||
|
//
|
||
|
|
||
|
// XXTF - FIXFIX - Merced specific.
|
||
|
UCHAR pmc0, overflow;
|
||
|
ULONG source;
|
||
|
|
||
|
HalpProfilingInterrupts++;
|
||
|
|
||
|
pmc0 = (UCHAR)HalpReadPerfMonCnfgReg0();
|
||
|
ASSERTMSG( "HAL!HalpProfileInterrupt PMC0 freeze bit is not set!\n", pmc0 & 0x1 );
|
||
|
overflow = pmc0 & 0xF0;
|
||
|
ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", overflow );
|
||
|
if ( overflow & (1<<4) ) {
|
||
|
source = HalpProfileSource4; // XXTF - IfFaster - Coud used pmc.es
|
||
|
ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < ProfileIA64Maximum );
|
||
|
KeProfileInterruptWithSource( TrapFrame, source );
|
||
|
HalpSetProfileCounterInterval( 4, HalpProfileMapping[source].Interval );
|
||
|
// XXTF - IfFaster - HalpWritePerfMonDataReg( 4, HalpProfileMapping[source].Interval );
|
||
|
// XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 4, *PCRProfileCnfg4Reload );
|
||
|
}
|
||
|
if ( overflow & (1<<5) ) {
|
||
|
source = HalpProfileSource5; // XXTF - IfFaster - Coud used pmc.es
|
||
|
ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < ProfileIA64Maximum );
|
||
|
KeProfileInterruptWithSource( TrapFrame, source );
|
||
|
HalpSetProfileCounterInterval( 5, HalpProfileMapping[source].Interval );
|
||
|
// XXTF - IfFaster - HalpWritePerfMonDataReg( 5, HalpProfileMapping[source].Interval );
|
||
|
// XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 5, *PCRProfileCnfg5Reload );
|
||
|
}
|
||
|
if ( overflow & (1<<6) ) {
|
||
|
source = HalpProfileSource6; // XXTF - IfFaster - Coud used pmc.es
|
||
|
ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < ProfileIA64Maximum );
|
||
|
KeProfileInterruptWithSource( TrapFrame, source );
|
||
|
HalpSetProfileCounterInterval( 6, HalpProfileMapping[source].Interval );
|
||
|
// XXTF - IfFaster - HalpWritePerfMonDataReg( 6, HalpProfileMapping[source].Interval );
|
||
|
// XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 6, *PCRProfileCnfg6Reload );
|
||
|
}
|
||
|
if ( overflow & (1<<7) ) {
|
||
|
source = HalpProfileSource7; // XXTF - IfFaster - Coud used pmc.es
|
||
|
ASSERTMSG( "HAL!HalpProfileInterrupt no overflow bit set!\n", source < ProfileIA64Maximum );
|
||
|
KeProfileInterruptWithSource( TrapFrame, source );
|
||
|
HalpSetProfileCounterInterval( 7, HalpProfileMapping[source].Interval );
|
||
|
// XXTF - IfFaster - HalpWritePerfMonDataReg( 6, HalpProfileMapping[source].Interval );
|
||
|
// XXTF - CodeWithReload - HalpWritePerfMonCnfgReg( 7, *PCRProfileCnfg7Reload );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Clear pmc0.fr and overflow bits.
|
||
|
//
|
||
|
|
||
|
HalpEnableProfileCounting();
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
HalpProfilingInterruptsWithoutProfiling++;
|
||
|
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpProfileInterrupt()
|
||
|
|
||
|
PHALP_PROFILE_MAPPING
|
||
|
HalpGetProfileMapping(
|
||
|
IN KPROFILE_SOURCE Source
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given a profile source, returns whether or not that source is
|
||
|
supported.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Source - Supplies the profile source
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - Profile source is supported
|
||
|
|
||
|
FALSE - Profile source is not supported
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
if ( Source > ProfileIA64Maximum /* = (sizeof(HalpProfileMapping)/sizeof(HalpProfileMapping[0])) */ )
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return(&HalpProfileMapping[Source]);
|
||
|
|
||
|
} // HalpGetProfileMapping()
|
||
|
|
||
|
BOOLEAN
|
||
|
HalQueryProfileInterval(
|
||
|
IN KPROFILE_SOURCE Source
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given a profile source, returns whether or not that source is
|
||
|
supported.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Source - Supplies the profile source
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - Profile source is supported
|
||
|
|
||
|
FALSE - Profile source is not supported
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PHALP_PROFILE_MAPPING profileMapping;
|
||
|
|
||
|
profileMapping = HalpGetProfileMapping( Source );
|
||
|
if ( !profileMapping ) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
return( profileMapping->Supported );
|
||
|
|
||
|
} // HalQueryProfileInterval()
|
||
|
|
||
|
NTSTATUS
|
||
|
HalSetProfileSourceInterval(
|
||
|
IN KPROFILE_SOURCE ProfileSource,
|
||
|
IN OUT ULONG_PTR *Interval
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Sets the profile interval for a specified profile source
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ProfileSource - Supplies the profile source
|
||
|
|
||
|
Interval - Supplies the specified profile interval
|
||
|
Returns the actual profile interval
|
||
|
|
||
|
- if ProfileSource is ProfileTime, Interval is in 100ns units.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NTSTATUS
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONGLONG countEvents;
|
||
|
PHALP_PROFILE_MAPPING profileMapping;
|
||
|
|
||
|
profileMapping = HalpGetProfileMapping(ProfileSource);
|
||
|
if ( HalpIsProfileMappingInvalid( profileMapping ) ) {
|
||
|
return(STATUS_NOT_IMPLEMENTED);
|
||
|
}
|
||
|
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: ProfileSource = %ld IN *Interval = 0x%Ix\n", ProfileSource, *Interval ));
|
||
|
|
||
|
if ( ProfileSource == ProfileTime ) {
|
||
|
//
|
||
|
// Convert the clock tick period (in 100ns units) into a cycle count period
|
||
|
//
|
||
|
countEvents = (ULONGLONG)(*Interval * HalpITCTicksPer100ns);
|
||
|
}
|
||
|
else {
|
||
|
countEvents = (ULONGLONG)*Interval;
|
||
|
}
|
||
|
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: countEvent = 0x%I64x\n", countEvents ));
|
||
|
|
||
|
//
|
||
|
// Check to see if the desired Interval is reasonable, if not adjust it.
|
||
|
//
|
||
|
|
||
|
if ( countEvents > profileMapping->MaxInterval ) {
|
||
|
countEvents = profileMapping->MaxInterval;
|
||
|
}
|
||
|
else if ( countEvents < profileMapping->MinInterval ) {
|
||
|
countEvents = profileMapping->MinInterval;
|
||
|
}
|
||
|
profileMapping->Interval = countEvents;
|
||
|
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: CurrentInterval = 0x%I64x\n", profileMapping->Interval ));
|
||
|
|
||
|
if ( ProfileSource == ProfileTime ) {
|
||
|
ULONGLONG tempInterval;
|
||
|
|
||
|
//
|
||
|
// Convert cycle count back into 100ns clock ticks
|
||
|
//
|
||
|
|
||
|
tempInterval = (ULONGLONG)(countEvents / HalpITCTicksPer100ns);
|
||
|
#if 0
|
||
|
if ( tempInterval < 1 ) {
|
||
|
tempInterval = 1;
|
||
|
}
|
||
|
#endif
|
||
|
*Interval = (ULONG_PTR)tempInterval;
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
*Interval = (ULONG_PTR)countEvents;
|
||
|
}
|
||
|
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalSetProfileSourceInterval: ProfileSource = %ld OUT *Interval = 0x%Ix\n", ProfileSource, *Interval ));
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
|
||
|
} // HalSetProfileSourceInterval()
|
||
|
|
||
|
ULONG_PTR
|
||
|
HalSetProfileInterval (
|
||
|
IN ULONG_PTR Interval
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine sets the ProfileTime source interrupt interval.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Interval - Supplies the desired profile interval in 100ns units.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The actual profile interval.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
ULONG_PTR NewInterval;
|
||
|
|
||
|
NewInterval = Interval;
|
||
|
HalSetProfileSourceInterval(ProfileTime, &NewInterval);
|
||
|
return(NewInterval);
|
||
|
|
||
|
} // HalSetProfileInterval()
|
||
|
|
||
|
VOID
|
||
|
HalStartProfileInterrupt (
|
||
|
KPROFILE_SOURCE ProfileSource
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine turns on the profile interrupt.
|
||
|
|
||
|
N.B. This routine must be called at PROFILE_LEVEL while holding the profile lock if MP.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
BOOLEAN disabledProfileCounting;
|
||
|
NTSTATUS status;
|
||
|
PHALP_PROFILE_MAPPING profileMapping;
|
||
|
|
||
|
//
|
||
|
// Get the Hal profile mapping entry associated with the specified source.
|
||
|
//
|
||
|
|
||
|
profileMapping = HalpGetProfileMapping( ProfileSource );
|
||
|
if ( HalpIsProfileMappingInvalid( profileMapping ) ) {
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalStartProfileInterrupt: invalid source = %ld\n", ProfileSource ));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Disable the profile counting if enabled.
|
||
|
//
|
||
|
|
||
|
disabledProfileCounting = FALSE;
|
||
|
if ( HalpProfilingRunning && !(HalpReadPerfMonCnfgReg0() & 0x1) ) {
|
||
|
HalpDisableProfileCounting();
|
||
|
disabledProfileCounting = TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Obtain and initialize an available PMC register that supports this event.
|
||
|
// We may enable more than one event.
|
||
|
// If the initialization failed, we return immediately.
|
||
|
//
|
||
|
// XXTF - FIXFIX - is there a way to
|
||
|
// * notify the caller for the failure and the reason of the failure. or
|
||
|
// * modify the API. or
|
||
|
// * define a new API.
|
||
|
//
|
||
|
|
||
|
status = HalpProgramProfileMapping( profileMapping, ProfileSource );
|
||
|
if ( !NT_SUCCESS(status) ) {
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalStartProfileInterrupt: HalpProgramProfileMapping failed.\n" ));
|
||
|
if ( disabledProfileCounting ) {
|
||
|
HalpEnableProfileCounting();
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Notify the profiling as active.
|
||
|
// before enabling the selected pmc overflow interrupt and unfreezing the counters.
|
||
|
//
|
||
|
|
||
|
HalpProfilingRunning++;
|
||
|
HalpEnableProfileCounting();
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalStartProfileInterrupt()
|
||
|
|
||
|
VOID
|
||
|
HalStopProfileInterrupt (
|
||
|
KPROFILE_SOURCE ProfileSource
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine turns off the profile interrupt.
|
||
|
|
||
|
N.B. This routine must be called at PROFILE_LEVEL while holding the
|
||
|
profile lock.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ProfileSource - Supplies the Profile Source to stop.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PHALP_PROFILE_MAPPING profileMapping;
|
||
|
|
||
|
//
|
||
|
// Get the Hal profile mapping entry associated with the specified profile source.
|
||
|
//
|
||
|
|
||
|
profileMapping = HalpGetProfileMapping( ProfileSource );
|
||
|
if ( HalpIsProfileMappingInvalid( profileMapping ) ) {
|
||
|
HalDebugPrint(( HAL_PROFILE, "HalStopProfileInterrupt: invalid source = %ld\n", ProfileSource ));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Validate the Profile Source as active.
|
||
|
//
|
||
|
|
||
|
if ( HalpProfileSource4 == ProfileSource ) {
|
||
|
|
||
|
// XXTF - FIXFIX - Derived Event - ToBeDone
|
||
|
|
||
|
HalpSetProfileCounterConfiguration( 4,
|
||
|
PMC_PLM_NONE,
|
||
|
PMC_DISABLE_OVERFLOW_INTERRUPT,
|
||
|
PMC_DISABLE_PRIVILEGE_MONITOR,
|
||
|
0, // Event
|
||
|
0, // Umask
|
||
|
0, // Threshold
|
||
|
PMC_ISM_NONE
|
||
|
);
|
||
|
|
||
|
HalpSetProfileCounterInterval( 4, 0 );
|
||
|
HalpDisactivateProfileSource( HalpProfileSource4 );
|
||
|
HalpProfilingRunning--;
|
||
|
|
||
|
}
|
||
|
else if ( HalpProfileSource5 == ProfileSource ) {
|
||
|
|
||
|
// XXTF - FIXFIX - Derived Event - ToBeDone
|
||
|
|
||
|
HalpSetProfileCounterConfiguration( 5,
|
||
|
PMC_PLM_NONE,
|
||
|
PMC_DISABLE_OVERFLOW_INTERRUPT,
|
||
|
PMC_DISABLE_PRIVILEGE_MONITOR,
|
||
|
0, // Event
|
||
|
0, // Umask
|
||
|
0, // Threshold
|
||
|
PMC_ISM_NONE
|
||
|
);
|
||
|
|
||
|
HalpSetProfileCounterInterval( 5, 0 );
|
||
|
HalpDisactivateProfileSource( HalpProfileSource5 );
|
||
|
HalpProfilingRunning--;
|
||
|
|
||
|
}
|
||
|
else if ( HalpProfileSource6 == ProfileSource ) {
|
||
|
|
||
|
// XXTF - FIXFIX - Derived Event - ToBeDone
|
||
|
|
||
|
HalpSetProfileCounterConfiguration( 6,
|
||
|
PMC_PLM_NONE,
|
||
|
PMC_DISABLE_OVERFLOW_INTERRUPT,
|
||
|
PMC_DISABLE_PRIVILEGE_MONITOR,
|
||
|
0, // Event
|
||
|
0, // Umask
|
||
|
0, // Threshold
|
||
|
PMC_ISM_NONE
|
||
|
);
|
||
|
|
||
|
HalpSetProfileCounterInterval( 6, 0 );
|
||
|
HalpDisactivateProfileSource( HalpProfileSource6);
|
||
|
HalpProfilingRunning--;
|
||
|
|
||
|
}
|
||
|
else if ( HalpProfileSource7 == ProfileSource ) {
|
||
|
|
||
|
// XXTF - FIXFIX - Derived Event - ToBeDone
|
||
|
|
||
|
HalpSetProfileCounterConfiguration( 7,
|
||
|
PMC_PLM_NONE,
|
||
|
PMC_DISABLE_OVERFLOW_INTERRUPT,
|
||
|
PMC_DISABLE_PRIVILEGE_MONITOR,
|
||
|
0, // Event
|
||
|
0, // Umask
|
||
|
0, // Threshold
|
||
|
PMC_ISM_NONE
|
||
|
);
|
||
|
|
||
|
HalpSetProfileCounterInterval( 7, 0 );
|
||
|
HalpDisactivateProfileSource( HalpProfileSource7 );
|
||
|
HalpProfilingRunning--;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalStopProfileInterrupt()
|
||
|
|
||
|
VOID
|
||
|
HalpResetProcessorDependentPerfMonCnfgRegs(
|
||
|
ULONGLONG DefaultValue
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine initializes the processor dependent performance configuration
|
||
|
registers.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DefaultValue - default value used to initialize IA64 generic PMCs.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
// XXTF - 02/08/2000
|
||
|
// For now, there is no initialization for processor dependent performance
|
||
|
// configuration registers.
|
||
|
return;
|
||
|
|
||
|
} // HalpResetProcessorDependentPerfMonCnfgRegs()
|
||
|
|
||
|
VOID
|
||
|
HalpResetPerfMonCnfgRegs(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine initializes the IA64 architected performance configuration
|
||
|
registers and calls the micro-architecture specific initialization.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONG pmc;
|
||
|
ULONGLONG value;
|
||
|
|
||
|
//
|
||
|
// PMC Reset value:
|
||
|
// Reg. Field Bits
|
||
|
// PMC* .plm - 3: 0 - Privilege Mask - 0 (Disable Counter)
|
||
|
// PMC* .ev - 4 - External Visibility - 0 (Disabled)
|
||
|
// PMC* .oi - 5 - Overflow Interrupt - 0 (Disabled)
|
||
|
// PMC* .pm - 6 - Privilege Monitor - 0 (user monitor)
|
||
|
// PMC* .ig - 7 - Ignored
|
||
|
// PMC* .es - 14: 8 - Event Select - 0 (XXTF - Warning - 0x0 = Real Event)
|
||
|
// PMC* .ig - 15 - Ignored
|
||
|
// PMC* .umask - 19:16 - Unit Mask - 0 (event specific. ok for .es=0)
|
||
|
// PMC4,5 .threshold - 22:20 - Threshold - 0 (multi-occurence events threshold)
|
||
|
// PMC4,5 .ig - 23 - Ignored
|
||
|
// PMC6,7 .threshold - 21:20 - Threshold - 0 (multi-occurence events threshold)
|
||
|
// PMC6,7 .ig - 23:22 - Ignored
|
||
|
// PMC* .ism - 25:24 - Instruction Set Mask - 0 (IA64 & IA32 sets - 11:disables monitoring)
|
||
|
// PMC* .ig - 63:26 - Ignored
|
||
|
// -----
|
||
|
// PMC_RESET
|
||
|
|
||
|
#define PMC_RESET 0ui64
|
||
|
|
||
|
value = PMC_RESET;
|
||
|
for ( pmc = 4; pmc < 8; pmc++ ) {
|
||
|
HalpWritePerfMonCnfgReg( pmc, value );
|
||
|
}
|
||
|
|
||
|
HalpResetProcessorDependentPerfMonCnfgRegs( value );
|
||
|
|
||
|
#undef PMC_RESET
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpResetPerfMonCnfgRegs()
|
||
|
|
||
|
VOID
|
||
|
HalpInitializeProfiling (
|
||
|
ULONG Number
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is called during initialization to initialize profiling
|
||
|
for each processor in the system.
|
||
|
|
||
|
Called from HalInitSystem at phase 1 on every processor.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Number - Supplies the processor number.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// If BSP processor, initialize the ProfileTime Interval entries.
|
||
|
//
|
||
|
// Assumes HalpITCTicksPer100ns has been initialized.
|
||
|
|
||
|
if ( Number == 0 ) {
|
||
|
ULONGLONG interval;
|
||
|
ULONGLONG count;
|
||
|
PHALP_PROFILE_MAPPING profile;
|
||
|
|
||
|
profile = &HalpProfileMapping[ProfileTime];
|
||
|
|
||
|
interval = DEFAULT_PROFILE_INTERVAL;
|
||
|
count = (ULONGLONG)(interval * HalpITCTicksPer100ns);
|
||
|
profile->DefInterval = count;
|
||
|
|
||
|
interval = MAXIMUM_PROFILE_INTERVAL;
|
||
|
count = (ULONGLONG)(interval * HalpITCTicksPer100ns);
|
||
|
profile->MaxInterval = count;
|
||
|
|
||
|
interval = MINIMUM_PROFILE_INTERVAL;
|
||
|
count = (ULONGLONG)(interval * HalpITCTicksPer100ns);
|
||
|
profile->MinInterval = count;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ToBeDone - checkpoint for default processor.PSR fields for
|
||
|
// performance monitoring.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Resets the processor performance configuration registers.
|
||
|
//
|
||
|
|
||
|
HalpResetPerfMonCnfgRegs();
|
||
|
|
||
|
//
|
||
|
// Initialization of the Per processor profiling data.
|
||
|
//
|
||
|
|
||
|
HalpProfilingRunning = 0;
|
||
|
HalpDisactivateProfileSource( HalpProfileSource4 );
|
||
|
HalpDisactivateProfileSource( HalpProfileSource5 );
|
||
|
HalpDisactivateProfileSource( HalpProfileSource6 );
|
||
|
HalpDisactivateProfileSource( HalpProfileSource7 );
|
||
|
|
||
|
//
|
||
|
// XXTF 02/08/2000:
|
||
|
// Different performance vectors are considered:
|
||
|
// - Profiling (default) -> PROFILE_VECTOR
|
||
|
// - Tracing -> PERF_VECTOR [PMUTRACE_VECTOR]
|
||
|
//
|
||
|
// Set default Performance vector to Profiling.
|
||
|
//
|
||
|
|
||
|
ASSERTMSG( "HAL!HalpInitializeProfiler PROFILE_VECTOR handler != HalpProfileInterrupt\n",
|
||
|
PCR->InterruptRoutine[PROFILE_VECTOR] == (PKINTERRUPT_ROUTINE)HalpProfileInterrupt );
|
||
|
|
||
|
HalpWritePerfMonVectorReg( PROFILE_VECTOR );
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // HalpInitializeProfiler()
|
||
|
|
||
|
NTSTATUS
|
||
|
HalpProfileSourceInformation (
|
||
|
OUT PVOID Buffer,
|
||
|
IN ULONG BufferLength,
|
||
|
OUT PULONG ReturnedLength
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Returns the HAL_PROFILE_SOURCE_INFORMATION or
|
||
|
HAL_PROFILE_SOURCE_INFORMATION_EX for this processor.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Buffer - output buffer
|
||
|
BufferLength - length of buffer on input
|
||
|
ReturnedLength - The length of data returned
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_SUCCESS
|
||
|
STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
|
||
|
currently needed.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PHALP_PROFILE_MAPPING profileMapping;
|
||
|
NTSTATUS status;
|
||
|
|
||
|
if ( (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) &&
|
||
|
(BufferLength < sizeof(HAL_PROFILE_SOURCE_INFORMATION_EX)) )
|
||
|
{
|
||
|
status = STATUS_INFO_LENGTH_MISMATCH;
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
profileMapping = HalpGetProfileMapping(((PHAL_PROFILE_SOURCE_INFORMATION)Buffer)->Source);
|
||
|
//
|
||
|
// return a different status error if the source is not supported or
|
||
|
// the source is not a valid
|
||
|
//
|
||
|
|
||
|
if ( profileMapping == NULL ) {
|
||
|
status = STATUS_INVALID_PARAMETER;
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
if ( BufferLength == sizeof(HAL_PROFILE_SOURCE_INFORMATION) ) {
|
||
|
|
||
|
PHAL_PROFILE_SOURCE_INFORMATION sourceInfo;
|
||
|
|
||
|
//
|
||
|
// HAL_PROFILE_SOURCE_INFORMATION buffer.
|
||
|
//
|
||
|
|
||
|
sourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
|
||
|
sourceInfo->Supported = profileMapping->Supported;
|
||
|
if ( sourceInfo->Supported ) {
|
||
|
|
||
|
//
|
||
|
// For ProfileTime, we convert cycle count back into 100ns clock ticks.
|
||
|
//
|
||
|
|
||
|
if ( profileMapping->ProfileSource == ProfileTime ) {
|
||
|
sourceInfo->Interval = (ULONG) (profileMapping->Interval / HalpITCTicksPer100ns);
|
||
|
}
|
||
|
else {
|
||
|
sourceInfo->Interval = (ULONG) profileMapping->Interval;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( ReturnedLength ) {
|
||
|
*ReturnedLength = sizeof(HAL_PROFILE_SOURCE_INFORMATION);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
PHAL_PROFILE_SOURCE_INFORMATION_EX sourceInfoEx;
|
||
|
|
||
|
//
|
||
|
// HAL_PROFILE_SOURCE_INFORMATION_EX buffer.
|
||
|
//
|
||
|
|
||
|
sourceInfoEx = (PHAL_PROFILE_SOURCE_INFORMATION_EX)Buffer;
|
||
|
sourceInfoEx->Supported = profileMapping->Supported;
|
||
|
if ( sourceInfoEx->Supported ) {
|
||
|
|
||
|
//
|
||
|
// For ProfileTime, we convert cycle count back into 100ns clock ticks.
|
||
|
//
|
||
|
|
||
|
if ( profileMapping->ProfileSource == ProfileTime ) {
|
||
|
sourceInfoEx->Interval = (ULONG_PTR) (profileMapping->Interval / HalpITCTicksPer100ns);
|
||
|
}
|
||
|
else {
|
||
|
sourceInfoEx->Interval = (ULONG_PTR) profileMapping->Interval;
|
||
|
}
|
||
|
|
||
|
sourceInfoEx->DefInterval = (ULONG_PTR) profileMapping->DefInterval;
|
||
|
sourceInfoEx->MaxInterval = (ULONG_PTR) profileMapping->MaxInterval;
|
||
|
sourceInfoEx->MinInterval = (ULONG_PTR) profileMapping->MinInterval;
|
||
|
}
|
||
|
|
||
|
if ( ReturnedLength ) {
|
||
|
*ReturnedLength = sizeof(HAL_PROFILE_SOURCE_INFORMATION_EX);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
|
||
|
} // HalpProfileSourceInformation()
|
||
|
|