366 lines
9.4 KiB
C
366 lines
9.4 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1992 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
ia64 pmc
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
KD Extension Api
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Thierry Fevrier (v-thief)
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
User Mode.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
#include "ia64.h"
|
||
|
|
||
|
//
|
||
|
// EmPmcFields: EM register fields for the Performance Monitor Counter register.
|
||
|
//
|
||
|
|
||
|
EM_REG_FIELD EmGenPmcFields[] = {
|
||
|
{ "plm", "Privilege Level Mask" , 0x4, 0 }, // 0-3
|
||
|
{ "ev", "External Visibility" , 0x1, 4 }, // 4
|
||
|
{ "oi", "Overflow Interrupt", 0x1, 5 }, // 5
|
||
|
{ "pm", "Privileged Monitor", 0x1, 6 }, // 6
|
||
|
{ "ig", "ignored1", 0x1, 7 }, // 7
|
||
|
{ "es", "Event Selection", 0x7, 8 }, // 8-14
|
||
|
{ "ig", "ignored2", 0x1, 15 }, // 15
|
||
|
{ "umk", "Unit Mask", 0x4, 16 }, // 16-19
|
||
|
{ "thr", "Event Threshold", 0x3, 20 }, // 20-[21-22]
|
||
|
{ "ig", "ignored3", 0x1, 23 }, // 23
|
||
|
{ "ism", "Instruction Set Mask", 0x2, 24 }, // 24-25
|
||
|
{ "ig", "ignored4", 0x26, 26 } // 26-63
|
||
|
};
|
||
|
|
||
|
EM_REG_FIELD EmBtbPmcFields[] = {
|
||
|
{ "plm", "Privilege Level Mask", 0x4, 0 }, // 0-3
|
||
|
{ "ign", "ignored1", 0x2, 4 }, // 4-5
|
||
|
{ "pm" , "Privileged Monitor", 0x1, 6}, // 6
|
||
|
{ "tar", "Target Address Register", 0x1, 7 }, // 7
|
||
|
{ "tm" , "Taken Mask", 0x2, 8 }, // 8-9
|
||
|
{ "ptm", "Predicted Target Address Mask", 0x2, 10 }, // 10-11
|
||
|
{ "ppm", "Predicted Predicate Mask", 0x2, 12 }, // 12-13
|
||
|
{ "bpt", "Branch Prediction Table", 0x1, 14 }, // 14
|
||
|
{ "bac", "Branch Address Calculator", 0x1, 15 }, // 15
|
||
|
{ "ign", "ignored2", 0x30, 16 } // 16-63
|
||
|
};
|
||
|
|
||
|
EM_REG_FIELD EmBtbPmdFields[] = {
|
||
|
{ "b", "Branch Bit", 0x1, 0 }, // 0
|
||
|
{ "mp", "Mispredit Bit", 0x1, 1 }, // 1
|
||
|
{ "slt", "Instruction Slot", 0x2, 2}, // 2-3
|
||
|
{ "add", "Address", 0x3c, 4 } // 4-63
|
||
|
};
|
||
|
|
||
|
EM_REG_FIELD EmBtbIndexPmdFields[] = {
|
||
|
{ "bbi", "Branch Buffer Index", 0x3, 0 }, // 0-2
|
||
|
{ "ful", "Full Bit", 0x1, 3 }, // 3
|
||
|
{ "ign", "ignored", 0x3c, 4 } // 4-63
|
||
|
};
|
||
|
|
||
|
typedef
|
||
|
VOID
|
||
|
(*PDISPLAY_PMC)(
|
||
|
IN const PCHAR Header,
|
||
|
IN ULONG64 PmcValue,
|
||
|
IN DISPLAY_MODE DisplayMode
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
DisplayPmcIA64(
|
||
|
IN const PCHAR Header,
|
||
|
IN ULONG64 PmcValue,
|
||
|
IN DISPLAY_MODE DisplayMode
|
||
|
)
|
||
|
{
|
||
|
|
||
|
dprintf("%s0x%I64x\n", ( Header ? Header : " pmc: " ), PmcValue );
|
||
|
return;
|
||
|
|
||
|
} // DisplayPmcIA64()
|
||
|
|
||
|
VOID
|
||
|
DisplayGenPmcIA64(
|
||
|
IN const PCHAR Header,
|
||
|
IN ULONG64 PmcValue,
|
||
|
IN DISPLAY_MODE DisplayMode
|
||
|
)
|
||
|
{
|
||
|
dprintf("%s", Header ? Header : "" );
|
||
|
if ( DisplayMode >= DISPLAY_MED ) {
|
||
|
DisplayFullEmReg( PmcValue, EmGenPmcFields, DisplayMode );
|
||
|
}
|
||
|
else {
|
||
|
EM_PMC emPmc;
|
||
|
|
||
|
emPmc = ULong64ToEM_PMC( PmcValue );
|
||
|
dprintf(
|
||
|
"plm ev oi pm es umk thr ism\n "
|
||
|
"%1I64x %1I64x %1I64x %1I64x %2I64x %1I64x %1I64x %1I64x\n",
|
||
|
emPmc.plm,
|
||
|
emPmc.ev,
|
||
|
emPmc.oi,
|
||
|
emPmc.pm,
|
||
|
emPmc.es,
|
||
|
emPmc.umask,
|
||
|
emPmc.threshold,
|
||
|
emPmc.ism
|
||
|
);
|
||
|
}
|
||
|
return;
|
||
|
} // DisplayGenPmcIA64()
|
||
|
|
||
|
VOID
|
||
|
DisplayBtbPmcIA64(
|
||
|
IN const PCHAR Header,
|
||
|
IN ULONG64 PmcValue,
|
||
|
IN DISPLAY_MODE DisplayMode
|
||
|
)
|
||
|
{
|
||
|
dprintf("%s", Header ? Header : "" );
|
||
|
if ( DisplayMode >= DISPLAY_MED ) {
|
||
|
DisplayFullEmReg( PmcValue, EmBtbPmcFields, DisplayMode );
|
||
|
}
|
||
|
else {
|
||
|
EM_BTB_PMC emPmc;
|
||
|
|
||
|
emPmc = ULong64ToEM_BTB_PMC( PmcValue );
|
||
|
dprintf(
|
||
|
"plm pm tar tm ptm ppm bpt bac\n "
|
||
|
"%1I64x %1I64x %1I64x %1I64x %1I64x %1I64x %1I64x %1I64x\n",
|
||
|
emPmc.plm,
|
||
|
emPmc.pm,
|
||
|
emPmc.tar,
|
||
|
emPmc.tm,
|
||
|
emPmc.ptm,
|
||
|
emPmc.ppm,
|
||
|
emPmc.bpt,
|
||
|
emPmc.bac
|
||
|
);
|
||
|
}
|
||
|
return;
|
||
|
} // DisplayBtbPmcIA64()
|
||
|
|
||
|
VOID
|
||
|
DisplayBtbPmdIA64(
|
||
|
IN const PCHAR Header, // Header string displayed before pmc.
|
||
|
IN ULONG64 PmdValue, // PMD value.
|
||
|
IN DISPLAY_MODE DisplayMode // Display mode.
|
||
|
)
|
||
|
{
|
||
|
|
||
|
|
||
|
dprintf("%s", Header ? Header : "" );
|
||
|
if ( DisplayMode >= DISPLAY_MED ) {
|
||
|
DisplayFullEmReg( PmdValue, EmBtbPmdFields, DisplayMode );
|
||
|
}
|
||
|
else {
|
||
|
EM_BTB_PMD btbPmd;
|
||
|
ULONG64 brAddress;
|
||
|
|
||
|
btbPmd = ULong64ToEM_BTB_PMD( PmdValue );
|
||
|
#define ITANIUM_PA_ADDRESSING_MASK 0x80000FFFFFFFFFFFUI64
|
||
|
#define ITANIUM_VA_ADDRESSING_MASK 0xE007FFFFFFFFFFFFUI64
|
||
|
#define ITANIUM_BTB_PMD_ADDRESS_MASK( _pmdValue) \
|
||
|
( ((_pmdValue) & 0xfffffffffffffff0UI64) & ITANIUM_VA_ADDRESSING_MASK )
|
||
|
|
||
|
brAddress = ITANIUM_BTB_PMD_ADDRESS_MASK( PmdValue );
|
||
|
dprintf(
|
||
|
"%1I64x %1I64x %1I64x 0x%016I64x ",
|
||
|
btbPmd.b,
|
||
|
btbPmd.mp,
|
||
|
btbPmd.slot,
|
||
|
brAddress
|
||
|
);
|
||
|
|
||
|
#if 0
|
||
|
// Thierry 03/19/2001 - BUGBUG
|
||
|
// Itanium Processor Programmer's guide does not present the
|
||
|
// PMD[8-15] branch/interrupt mode 2 formats.
|
||
|
// I am disabling this check until I can implement it correctly with a context
|
||
|
// that can distinguish between mode 1 and mode 2 at the time this history was created.
|
||
|
if ( (btbPmd.b == 0) && (btbPmd.mp == 0)) {
|
||
|
dprintf("<invalid entry>");
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
{
|
||
|
CCHAR symbol[256];
|
||
|
PCHAR s;
|
||
|
ULONG64 displacement;
|
||
|
|
||
|
symbol[0] = '!';
|
||
|
GetSymbol( brAddress, symbol, &displacement);
|
||
|
s = (PCHAR)symbol + strlen( (PCHAR)symbol );
|
||
|
if (s == (PCHAR)symbol ) {
|
||
|
sprintf( s, (IsPtr64() ? "0x%016I64x" : "0x%08x"), brAddress );
|
||
|
}
|
||
|
else {
|
||
|
if ( displacement ) {
|
||
|
sprintf( s, (IsPtr64() ? "+0x%I64x" : "+0x%x"), displacement );
|
||
|
}
|
||
|
}
|
||
|
dprintf( "%s", symbol );
|
||
|
}
|
||
|
dprintf("\n");
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // DisplayBtbPmdIA64()
|
||
|
|
||
|
VOID
|
||
|
DisplayBtbIndexPmdIA64(
|
||
|
IN const PCHAR Header,
|
||
|
IN ULONG64 PmcValue,
|
||
|
IN DISPLAY_MODE DisplayMode
|
||
|
)
|
||
|
{
|
||
|
dprintf("%s", Header ? Header : "" );
|
||
|
if ( DisplayMode >= DISPLAY_MED ) {
|
||
|
DisplayFullEmReg( PmcValue, EmBtbIndexPmdFields, DisplayMode );
|
||
|
}
|
||
|
else {
|
||
|
EM_BTB_INDEX_PMD emPmd;
|
||
|
|
||
|
emPmd = ULong64ToEM_BTB_INDEX_PMD( PmcValue );
|
||
|
dprintf(
|
||
|
"bbi full\n "
|
||
|
"%1I64x %1I64x\n",
|
||
|
emPmd.bbi,
|
||
|
emPmd.full
|
||
|
);
|
||
|
}
|
||
|
return;
|
||
|
} // DisplayBtbIndexPmdIA64()
|
||
|
|
||
|
PDISPLAY_PMC
|
||
|
GetPmcDisplayFunction(
|
||
|
char *Str
|
||
|
)
|
||
|
{
|
||
|
LONG pmc;
|
||
|
char *c;
|
||
|
|
||
|
c = Str;
|
||
|
while( isalnum( (int)(*c) ) ) {
|
||
|
c++;
|
||
|
}
|
||
|
*c = '\0';
|
||
|
|
||
|
pmc = atol( Str );
|
||
|
switch( pmc ) {
|
||
|
case 4:
|
||
|
case 5:
|
||
|
case 6:
|
||
|
case 7:
|
||
|
return( (PDISPLAY_PMC)DisplayGenPmcIA64 );
|
||
|
|
||
|
case 12:
|
||
|
return( (PDISPLAY_PMC)DisplayBtbPmcIA64 );
|
||
|
|
||
|
default:
|
||
|
if ( !strcmp( Str, "gen" ) ) {
|
||
|
return( (PDISPLAY_PMC)DisplayGenPmcIA64 );
|
||
|
}
|
||
|
if ( !strcmp( Str, "btb" ) ) {
|
||
|
return( (PDISPLAY_PMC)DisplayBtbPmcIA64 );
|
||
|
}
|
||
|
return ( (PDISPLAY_PMC)DisplayPmcIA64 );
|
||
|
}
|
||
|
|
||
|
} // IsPmcSupported()
|
||
|
|
||
|
DECLARE_API( pmc )
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Dumps a IA-64 Processor PMC Register.
|
||
|
// Thierry 11/2000: The following scheme could also be used for PMD registers.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
args - Supplies the address in hex.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
ULONG64 pmcValue = 0;
|
||
|
ULONG result;
|
||
|
ULONG flags = 0;
|
||
|
char *option = NULL;
|
||
|
PDISPLAY_PMC displayPmc = DisplayGenPmcIA64; // Default display function.
|
||
|
char *header;
|
||
|
|
||
|
if ( TargetMachine != IMAGE_FILE_MACHINE_IA64 )
|
||
|
{
|
||
|
dprintf("!pmc not implemented for this architecture.\n");
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
option = strchr( args, '-' );
|
||
|
if ( option ) {
|
||
|
displayPmc = GetPmcDisplayFunction( ++option );
|
||
|
args += (strlen(option) + 2);
|
||
|
}
|
||
|
|
||
|
result = sscanf(args,"%I64lx %lx", &pmcValue, &flags);
|
||
|
if ((result != 1) && (result != 2)) {
|
||
|
//
|
||
|
// If user specified "@kpfc*"...
|
||
|
//
|
||
|
|
||
|
char kpfcStr[16];
|
||
|
BOOLEAN valid = FALSE;
|
||
|
|
||
|
result = sscanf(args,"%s %lx", kpfcStr, &flags);
|
||
|
if ( (result == 1) || (result == 2) ) {
|
||
|
if ( option == NULL ) { // If we did not force the display format.
|
||
|
char *str;
|
||
|
|
||
|
str = strstr( kpfcStr, "@kpfc" );
|
||
|
if ( str ) {
|
||
|
str += strlen("@kpfc");
|
||
|
displayPmc = GetPmcDisplayFunction( str );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
dprintf( "USAGE: !pmc [-opt] 0xValue [display_mode:0,1,2]\n"
|
||
|
"USAGE: !pmc @kpfc* [display_mode:0,1,2]\n"
|
||
|
"where currently supported option:\n"
|
||
|
"\tgen [or 4,5,6,7] - generic PMC registers\n"
|
||
|
"\tbtb [or 12] - branch trace buffer PMC register\n"
|
||
|
"\tEx: !pmc -btb @r2 2\n"
|
||
|
);
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
pmcValue = GetExpression(kpfcStr);
|
||
|
}
|
||
|
|
||
|
header = (flags > DISPLAY_MIN) ? NULL : " pmc: ";
|
||
|
(*displayPmc)( header, pmcValue, flags );
|
||
|
|
||
|
return S_OK;
|
||
|
|
||
|
} // !pmc
|