Trace cache instrumentation methods

Next step will be tracing cross non-taken branches
This commit is contained in:
Stanislav Shwartsman 2007-12-14 11:27:44 +00:00
parent 48d815427c
commit db69a25c36
3 changed files with 77 additions and 48 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.cc,v 1.188 2007-12-09 18:36:03 sshwarts Exp $
// $Id: cpu.cc,v 1.189 2007-12-14 11:27:44 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -57,25 +57,30 @@ void flushICaches(void)
pageWriteStampTable.resetWriteStamps();
}
#define InstrumentICACHE 0
#define InstrumentTRACECACHE 0
#if InstrumentICACHE
#if InstrumentTRACECACHE
static Bit32u iCacheLookups=0;
static Bit32u iCacheMisses=0;
static Bit32u iCacheMergeTraces=0;
static Bit32u iCacheLength[BX_MAX_TRACE_LENGTH+1];
static Bit32u iCacheTraceLengh[BX_MAX_TRACE_LENGTH];
#define InstrICache_StatsMask 0xfffffff
#define InstrICache_Stats() {\
if ((iCacheLookups & InstrICache_StatsMask) == 0) { \
BX_INFO(("ICACHE lookups: %u, misses: %u, merges: %u, hit rate = %6.2f%% ", \
BX_INFO(("ICACHE lookups: %u, misses: %u, merges: %u, hit rate = %3.2f%%", \
(unsigned) iCacheLookups, \
(unsigned) iCacheMisses, \
(unsigned) iCacheMergeTraces, \
(iCacheLookups-iCacheMisses) * 100.0 / iCacheLookups)); \
for (unsigned trace_len_idx=0; trace_len_idx<BX_MAX_TRACE_LENGTH;trace_len_idx++) { \
BX_INFO(("trace[%02d]: %u\t(%3.2f%%)", trace_len_idx+1, \
iCacheTraceLengh[trace_len_idx], \
iCacheTraceLengh[trace_len_idx] * 100.0/(iCacheLookups-iCacheMisses))); \
iCacheTraceLengh[trace_len_idx] = 0; \
} \
iCacheLookups = iCacheMisses = iCacheMergeTraces = 0; \
for (int i=0;i<=BX_MAX_TRACE_LENGTH;i++) iCacheLength[i] = 0; \
} \
}
#define InstrICache_Increment(v) (v)++
@ -85,7 +90,7 @@ static Bit32u iCacheLength[BX_MAX_TRACE_LENGTH+1];
#define InstrICache_Increment(v)
#endif
#endif // BX_SUPPORT_ICACHE
#endif // InstrumentTRACECACHE
// Make code more tidy with a few macros.
#if BX_SUPPORT_X86_64==0
@ -108,6 +113,7 @@ bxICacheEntry_c* BX_CPU_C::fetchInstructionTrace(bxInstruction_c *iStorage, bx_a
if ((trace->pAddr == pAddr) &&
(trace->writeStamp == pageWriteStamp))
{
InstrICache_Increment(iCacheTraceLengh[trace->ilen-1]);
return trace; // We are lucky - trace cache hit !
}
@ -172,8 +178,6 @@ bxICacheEntry_c* BX_CPU_C::fetchInstructionTrace(bxInstruction_c *iStorage, bx_a
if (mergeTraces(trace, i, pAddr)) break;
}
InstrICache_Increment(iCacheLength[trace->ilen-1]);
return trace;
}
@ -202,6 +206,30 @@ bx_bool BX_CPU_C::mergeTraces(bxICacheEntry_c *trace, bxInstruction_c *i, bx_phy
return 0;
}
void BX_CPU_C::instrumentTraces(void)
{
Bit32u currPageWriteStamp = *(BX_CPU_THIS_PTR currPageWriteStampPtr);
bxICacheEntry_c *e = BX_CPU_THIS_PTR iCache.entry;
Bit32u trace_length[BX_MAX_TRACE_LENGTH], invalid_entries = 0;
unsigned i;
for (i=0; i < BX_MAX_TRACE_LENGTH; i++) trace_length[i] = 0;
for (i=0; i<BxICacheEntries; i++, e++) {
if (e->writeStamp == currPageWriteStamp)
trace_length[e->ilen-1]++;
else
invalid_entries++;
}
for (i=0; i < BX_MAX_TRACE_LENGTH; i++) {
BX_INFO(("traces[%02d]: %u\t%f%%", i+1,
trace_length[i], trace_length[i]*100.0/BxICacheEntries));
}
BX_INFO(("invalid entries: %u\t%f%%",
invalid_entries, invalid_entries*100.0/BxICacheEntries));
}
#else
bxInstruction_c* BX_CPU_C::fetchInstruction(bxInstruction_c *iStorage, bx_address eipBiased)

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.386 2007-12-09 18:36:04 sshwarts Exp $
// $Id: cpu.h,v 1.387 2007-12-14 11:27:44 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -2939,6 +2939,7 @@ public: // for now...
#if BX_SUPPORT_TRACE_CACHE
BX_SMF bxICacheEntry_c* fetchInstructionTrace(bxInstruction_c *, bx_address);
BX_SMF bx_bool mergeTraces(bxICacheEntry_c *trace, bxInstruction_c *i, bx_phy_address pAddr);
BX_SMF void instrumentTraces(void);
#else
BX_SMF bxInstruction_c* fetchInstruction(bxInstruction_c *, bx_address);
#endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.187 2007-12-14 10:15:12 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.188 2007-12-14 11:27:44 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -189,8 +189,6 @@ void BX_CPU_C::CLFLUSH(bxInstruction_c *i)
#if BX_CPU_LEVEL >= 3
void BX_CPU_C::MOV_DdRd(bxInstruction_c *i)
{
Bit32u val_32;
if (!real_mode() && CPL!=0) {
BX_ERROR(("MOV_DdRd: CPL!=0 not in real mode"));
exception(BX_GP_EXCEPTION, 0, 0);
@ -202,15 +200,15 @@ void BX_CPU_C::MOV_DdRd(bxInstruction_c *i)
* reg field specifies which special register
*/
invalidate_prefetch_q();
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
if (!i->modC0())
BX_PANIC(("MOV_DdRd(): rm field not a register!"));
invalidate_prefetch_q();
val_32 = BX_READ_32BIT_REG(i->rm());
Bit32u val_32 = BX_READ_32BIT_REG(i->rm());
switch (i->nnn()) {
case 0: // DR0
@ -325,6 +323,8 @@ void BX_CPU_C::MOV_RdDd(bxInstruction_c *i)
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
if (!i->modC0())
BX_PANIC(("MOV_RdDd(): rm field not a register!"));
switch (i->nnn()) {
case 0: // DR0
@ -389,18 +389,20 @@ void BX_CPU_C::MOV_DqRq(bxInstruction_c *i)
* reg field specifies which special register
*/
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
invalidate_prefetch_q();
/* #GP(0) if CPL is not 0 */
if (CPL != 0) {
BX_ERROR(("MOV_DqRq: #GP(0) if CPL is not 0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
invalidate_prefetch_q();
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
if (!i->modC0())
BX_PANIC(("MOV_DqRq(): rm field not a register!"));
Bit64u val_64 = BX_READ_64BIT_REG(i->rm());
switch (i->nnn()) {
@ -497,16 +499,18 @@ void BX_CPU_C::MOV_RqDq(bxInstruction_c *i)
BX_ASSERT(protected_mode());
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
/* #GP(0) if CPL is not 0 */
if (CPL != 0) {
BX_ERROR(("MOV_RqDq: #GP(0) if CPL is not 0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
if (!i->modC0())
BX_PANIC(("MOV_RqDq(): rm field not a register!"));
switch (i->nnn()) {
case 0: // DR0
val_64 = BX_CPU_THIS_PTR dr0;
@ -558,9 +562,6 @@ void BX_CPU_C::MOV_RqDq(bxInstruction_c *i)
void BX_CPU_C::MOV_CdRd(bxInstruction_c *i)
{
// mov general register data to control register
Bit32u val_32;
if (!real_mode() && CPL!=0) {
BX_ERROR(("MOV_CdRd: CPL!=0 not in real mode"));
exception(BX_GP_EXCEPTION, 0, 0);
@ -572,13 +573,15 @@ void BX_CPU_C::MOV_CdRd(bxInstruction_c *i)
* reg field specifies which special register
*/
invalidate_prefetch_q();
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
if (!i->modC0())
BX_PANIC(("MOV_CdRd(): rm field not a register!"));
invalidate_prefetch_q();
val_32 = BX_READ_32BIT_REG(i->rm());
Bit32u val_32 = BX_READ_32BIT_REG(i->rm());
switch (i->nnn()) {
case 0: // CR0 (MSW)
@ -674,9 +677,6 @@ void BX_CPU_C::MOV_RdCd(bxInstruction_c *i)
#if BX_SUPPORT_X86_64
void BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
{
// mov general register data to control register
Bit64u val_64;
BX_ASSERT(protected_mode());
/* NOTES:
@ -685,6 +685,12 @@ void BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
* reg field specifies which special register
*/
/* #GP(0) if CPL is not 0 */
if (CPL!=0) {
BX_ERROR(("MOV_CqRq: #GP(0) if CPL is not 0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
@ -693,13 +699,7 @@ void BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
invalidate_prefetch_q();
/* #GP(0) if CPL is not 0 */
if (CPL!=0) {
BX_ERROR(("MOV_CqRq: #GP(0) if CPL is not 0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
val_64 = BX_READ_64BIT_REG(i->rm());
Bit64u val_64 = BX_READ_64BIT_REG(i->rm());
switch (i->nnn()) {
case 0: // CR0 (MSW)
@ -760,18 +760,18 @@ void BX_CPU_C::MOV_RqCq(bxInstruction_c *i)
* reg field specifies which special register
*/
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
if (!i->modC0())
BX_PANIC(("MOV_RqCq(): rm field not a register!"));
/* #GP(0) if CPL is not 0 */
if (CPL!=0) {
BX_ERROR(("MOV_RqCq: #GP(0) if CPL is not 0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
/* This instruction is always treated as a register-to-register,
* regardless of the encoding of the MOD field in the MODRM byte.
*/
if (!i->modC0())
BX_PANIC(("MOV_RqCq(): rm field not a register!"));
switch (i->nnn()) {
case 0: // CR0 (MSW)
val_64 = BX_CPU_THIS_PTR cr0.val32;