introduced victim cache for a trace cache structure.
Allows to significantly cut trace cache miss latenct and find data in victim cahe instead of redoding it 8 entries VC in parallel with direct map 64K entries
This commit is contained in:
parent
9950c2a943
commit
4de76b0571
@ -192,7 +192,7 @@ bxICacheEntry_c* BX_CPU_C::getICacheEntry(void)
|
||||
// iCache miss. No validated instruction with matching fetch parameters
|
||||
// is in the iCache.
|
||||
InstrICache_Increment(iCacheMisses);
|
||||
serveICacheMiss(entry, (Bit32u) eipBiased, pAddr);
|
||||
entry = serveICacheMiss(entry, (Bit32u) eipBiased, pAddr);
|
||||
}
|
||||
|
||||
return entry;
|
||||
|
@ -2965,7 +2965,7 @@ public: // for now...
|
||||
BX_SMF int fetchDecode64(const Bit8u *fetchPtr, bxInstruction_c *i, unsigned remainingInPage) BX_CPP_AttrRegparmN(3);
|
||||
#endif
|
||||
BX_SMF void boundaryFetch(const Bit8u *fetchPtr, unsigned remainingInPage, bxInstruction_c *);
|
||||
BX_SMF void serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr);
|
||||
BX_SMF bxICacheEntry_c *serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr);
|
||||
BX_SMF bxICacheEntry_c* getICacheEntry(void);
|
||||
#if BX_SUPPORT_TRACE_CACHE
|
||||
BX_SMF bx_bool mergeTraces(bxICacheEntry_c *entry, bxInstruction_c *i, bx_phy_address pAddr);
|
||||
|
@ -1271,9 +1271,8 @@ BX_CPU_C::fetchDecode32(const Bit8u *iptr, bxInstruction_c *i, unsigned remainin
|
||||
unsigned sse_prefix = SSE_PREFIX_NONE;
|
||||
|
||||
int had_vex = 0;
|
||||
#if BX_SUPPORT_AVX
|
||||
int vvv = -1;
|
||||
unsigned vex;
|
||||
#if BX_SUPPORT_AVX
|
||||
bx_bool vex_w = 0;
|
||||
#endif
|
||||
|
||||
@ -1357,7 +1356,7 @@ fetch_b1:
|
||||
if ((attr & BxGroupX) == BxPrefixVEX && (*iptr & 0xc0) == 0xc0) {
|
||||
had_vex = 1;
|
||||
if (sse_prefix) had_vex = -1;
|
||||
unsigned vex_opcext = 1;
|
||||
unsigned vex, vex_opcext = 1;
|
||||
|
||||
if (remain != 0) {
|
||||
remain--;
|
||||
@ -1391,7 +1390,6 @@ fetch_b1:
|
||||
return(-1);
|
||||
|
||||
b1 += 256 * vex_opcext;
|
||||
|
||||
if (b1 < 256 || b1 >= 1024) had_vex = -1;
|
||||
else {
|
||||
if (b1 >= 512)
|
||||
@ -1434,9 +1432,10 @@ fetch_b1:
|
||||
|
||||
i->setNnn(nnn);
|
||||
#if BX_SUPPORT_AVX
|
||||
if (had_vex == 0) vvv = nnn;
|
||||
i->setVvv(vvv);
|
||||
if (had_vex == 0)
|
||||
#endif
|
||||
vvv = nnn;
|
||||
i->setVvv(vvv);
|
||||
|
||||
// MOVs with CRx and DRx always use register ops and ignore the mod field.
|
||||
if ((b1 & ~3) == 0x120)
|
||||
@ -1613,8 +1612,9 @@ modrm_done:
|
||||
case BxGroupN:
|
||||
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn]);
|
||||
#if BX_SUPPORT_AVX
|
||||
if (had_vex == 0) i->setVvv(rm);
|
||||
if (had_vex == 0)
|
||||
#endif
|
||||
i->setVvv(rm);
|
||||
break;
|
||||
case BxSplitGroupN:
|
||||
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn + (mod_mem << 3)]);
|
||||
|
@ -1704,9 +1704,8 @@ BX_CPU_C::fetchDecode64(const Bit8u *iptr, bxInstruction_c *i, unsigned remainin
|
||||
unsigned rex_prefix = 0;
|
||||
|
||||
int had_vex = 0;
|
||||
#if BX_SUPPORT_AVX
|
||||
int vvv = -1;
|
||||
unsigned vex;
|
||||
#if BX_SUPPORT_AVX
|
||||
bx_bool vex_w = 0;
|
||||
#endif
|
||||
|
||||
@ -1828,7 +1827,7 @@ fetch_b1:
|
||||
if ((attr & BxGroupX) == BxPrefixVEX) {
|
||||
had_vex = 1;
|
||||
if (sse_prefix || rex_prefix) had_vex = -1;
|
||||
unsigned vex_opcext = 1;
|
||||
unsigned vex, vex_opcext = 1;
|
||||
|
||||
if (remain != 0) {
|
||||
remain--;
|
||||
@ -1838,7 +1837,6 @@ fetch_b1:
|
||||
return(-1);
|
||||
|
||||
rex_r = ((vex >> 4) & 0x8) ^ 0x8;
|
||||
|
||||
if (b1 == 0xc4) {
|
||||
rex_x = ((vex >> 3) & 0x8) ^ 0x8;
|
||||
rex_b = ((vex >> 2) & 0x8) ^ 0x8;
|
||||
@ -1871,7 +1869,6 @@ fetch_b1:
|
||||
return(-1);
|
||||
|
||||
b1 += 256 * vex_opcext;
|
||||
|
||||
if (b1 < 256 || b1 >= 1024) had_vex = -1;
|
||||
else {
|
||||
if (b1 >= 512)
|
||||
@ -1914,9 +1911,10 @@ fetch_b1:
|
||||
|
||||
i->setNnn(nnn);
|
||||
#if BX_SUPPORT_AVX
|
||||
if (had_vex == 0) vvv = nnn;
|
||||
i->setVvv(vvv);
|
||||
if (had_vex == 0)
|
||||
#endif
|
||||
vvv = nnn;
|
||||
i->setVvv(vvv);
|
||||
|
||||
// MOVs with CRx and DRx always use register ops and ignore the mod field.
|
||||
if ((b1 & ~3) == 0x120)
|
||||
@ -2092,8 +2090,9 @@ modrm_done:
|
||||
case BxGroupN:
|
||||
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn & 0x7]);
|
||||
#if BX_SUPPORT_AVX
|
||||
if (had_vex == 0) i->setVvv(rm);
|
||||
if (had_vex == 0)
|
||||
#endif
|
||||
i->setVvv(rm);
|
||||
break;
|
||||
case BxSplitGroupN:
|
||||
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[(nnn & 0x7) + (mod_mem << 3)]);
|
||||
|
@ -57,8 +57,15 @@ void handleSMC(bx_phy_address pAddr, Bit32u mask)
|
||||
|
||||
#if BX_SUPPORT_TRACE_CACHE
|
||||
|
||||
void BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr)
|
||||
bxICacheEntry_c* BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr)
|
||||
{
|
||||
bxICacheEntry_c *vc_hit = BX_CPU_THIS_PTR iCache.lookup_victim_cache(pAddr, BX_CPU_THIS_PTR fetchModeMask);
|
||||
if (vc_hit) {
|
||||
return vc_hit;
|
||||
}
|
||||
|
||||
BX_CPU_THIS_PTR iCache.victim_entry(entry, BX_CPU_THIS_PTR fetchModeMask);
|
||||
|
||||
BX_CPU_THIS_PTR iCache.alloc_trace(entry);
|
||||
|
||||
// Cache miss. We weren't so lucky, but let's be optimistic - try to build
|
||||
@ -104,7 +111,7 @@ void BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_
|
||||
pageWriteStampTable.markICacheMask(entry->pAddr, entry->traceMask);
|
||||
pageWriteStampTable.markICacheMask(BX_CPU_THIS_PTR pAddrPage, 0x1);
|
||||
BX_CPU_THIS_PTR iCache.commit_page_split_trace(BX_CPU_THIS_PTR pAddrPage, entry);
|
||||
return;
|
||||
return entry;
|
||||
}
|
||||
|
||||
// add instruction to the trace
|
||||
@ -137,6 +144,8 @@ void BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_
|
||||
pageWriteStampTable.markICacheMask(pAddr, entry->traceMask);
|
||||
|
||||
BX_CPU_THIS_PTR iCache.commit_trace(entry->tlen);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
bx_bool BX_CPU_C::mergeTraces(bxICacheEntry_c *entry, bxInstruction_c *i, bx_phy_address pAddr)
|
||||
|
@ -137,6 +137,13 @@ public:
|
||||
bxICacheEntry_c *e; // Pointer to icache entry
|
||||
} pageSplitIndex[BX_ICACHE_PAGE_SPLIT_ENTRIES];
|
||||
int nextPageSplitIndex;
|
||||
|
||||
#define BX_ICACHE_VICTIM_ENTRIES 8 /* must be power of two */
|
||||
struct bxVictimCacheEntry {
|
||||
Bit32u fetchModeMask;
|
||||
bxICacheEntry_c vc_entry;
|
||||
} victimCache[BX_ICACHE_VICTIM_ENTRIES];
|
||||
int nextVictimCacheIndex;
|
||||
#endif
|
||||
|
||||
public:
|
||||
@ -173,11 +180,31 @@ public:
|
||||
|
||||
nextPageSplitIndex = (nextPageSplitIndex+1) & (BX_ICACHE_PAGE_SPLIT_ENTRIES-1);
|
||||
}
|
||||
|
||||
BX_CPP_INLINE bxICacheEntry_c *lookup_victim_cache(bx_phy_address pAddr, Bit32u fetchModeMask)
|
||||
{
|
||||
for (int i=0; i < BX_ICACHE_VICTIM_ENTRIES;i++) {
|
||||
bxVictimCacheEntry *e = &victimCache[i];
|
||||
if (e->vc_entry.pAddr == pAddr && e->fetchModeMask == fetchModeMask) {
|
||||
return &e->vc_entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BX_CPP_INLINE void victim_entry(bxICacheEntry_c *entry, Bit32u fetchModeMask)
|
||||
{
|
||||
if (entry->pAddr != BX_ICACHE_INVALID_PHY_ADDRESS) {
|
||||
victimCache[nextVictimCacheIndex].fetchModeMask = fetchModeMask;
|
||||
victimCache[nextVictimCacheIndex].vc_entry = *entry;
|
||||
nextVictimCacheIndex = (nextVictimCacheIndex+1) & (BX_ICACHE_VICTIM_ENTRIES-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BX_CPP_INLINE void handleSMC(bx_phy_address pAddr, Bit32u mask);
|
||||
|
||||
BX_CPP_INLINE void purgeICacheEntries(void);
|
||||
BX_CPP_INLINE void flushICacheEntries(void);
|
||||
|
||||
BX_CPP_INLINE bxICacheEntry_c* get_entry(bx_phy_address pAddr, unsigned fetchModeMask)
|
||||
@ -198,17 +225,22 @@ BX_CPP_INLINE void bxICache_c::flushICacheEntries(void)
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_TRACE_CACHE
|
||||
nextPageSplitIndex = 0;
|
||||
for (i=0;i<BX_ICACHE_PAGE_SPLIT_ENTRIES;i++)
|
||||
pageSplitIndex[i].ppf = BX_ICACHE_INVALID_PHY_ADDRESS;
|
||||
|
||||
nextPageSplitIndex = 0;
|
||||
nextVictimCacheIndex = 0;
|
||||
for (i=0;i<BX_ICACHE_VICTIM_ENTRIES;i++)
|
||||
victimCache[i].vc_entry.pAddr = BX_ICACHE_INVALID_PHY_ADDRESS;
|
||||
|
||||
mpindex = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: invalidate only entries in same page as pAddr
|
||||
BX_CPP_INLINE void bxICache_c::handleSMC(bx_phy_address pAddr, Bit32u mask)
|
||||
{
|
||||
// TODO: invalidate only entries in same page as pAddr
|
||||
unsigned i;
|
||||
|
||||
pAddr = LPFOf(pAddr);
|
||||
|
||||
@ -216,12 +248,17 @@ BX_CPP_INLINE void bxICache_c::handleSMC(bx_phy_address pAddr, Bit32u mask)
|
||||
if (mask & 0x1) {
|
||||
// the store touched 1st cache line in the page, check for
|
||||
// page split traces to invalidate.
|
||||
for (unsigned i=0;i<BX_ICACHE_PAGE_SPLIT_ENTRIES;i++) {
|
||||
for (i=0;i<BX_ICACHE_PAGE_SPLIT_ENTRIES;i++) {
|
||||
if (pAddr == pageSplitIndex[i].ppf) {
|
||||
pageSplitIndex[i].ppf = BX_ICACHE_INVALID_PHY_ADDRESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i < BX_ICACHE_VICTIM_ENTRIES; i++) {
|
||||
bxVictimCacheEntry *e = &victimCache[i];
|
||||
e->vc_entry.pAddr = BX_ICACHE_INVALID_PHY_ADDRESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
bxICacheEntry_c *e = get_entry(pAddr, 0);
|
||||
|
@ -38,6 +38,8 @@ typedef bx_address (BX_CPU_C::*BxResolvePtr_tR)(bxInstruction_c *) BX_CPP_AttrRe
|
||||
|
||||
extern bx_address bx_asize_mask[];
|
||||
|
||||
const char *get_bx_opcode_name(Bit16u ia_opcode);
|
||||
|
||||
// <TAG-CLASS-INSTRUCTION-START>
|
||||
class bxInstruction_c {
|
||||
public:
|
||||
@ -244,6 +246,9 @@ public:
|
||||
BX_CPP_INLINE void setIaOpcode(Bit16u op) {
|
||||
metaInfo.ia_opcode = (metaInfo.ia_opcode & 0xf000) | op;
|
||||
}
|
||||
BX_CPP_INLINE const char* getIaOpcodeName(void) const {
|
||||
return get_bx_opcode_name(getIaOpcode());
|
||||
}
|
||||
|
||||
BX_CPP_INLINE unsigned repUsedL(void) const {
|
||||
return metaInfo.metaInfo1 >> 6;
|
||||
@ -283,8 +288,6 @@ public:
|
||||
};
|
||||
// <TAG-CLASS-INSTRUCTION-END>
|
||||
|
||||
const char *get_bx_opcode_name(Bit16u ia_opcode);
|
||||
|
||||
enum {
|
||||
#define bx_define_opcode(a, b, c, d, e) a,
|
||||
#include "ia_opcodes.h"
|
||||
|
@ -475,7 +475,7 @@ void BX_CPP_AttrRegparmN(3) BX_CPU_C::VMexit_IO(bxInstruction_c *i, unsigned por
|
||||
break;
|
||||
|
||||
default:
|
||||
BX_PANIC(("VMexit_IO: I/O instruction %s unknown", get_bx_opcode_name(i->getIaOpcode())));
|
||||
BX_PANIC(("VMexit_IO: I/O instruction %s unknown", i->getIaOpcodeName()));
|
||||
}
|
||||
|
||||
if (qualification & VMX_VMEXIT_IO_INSTR_STRING) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user