cpu: Flush TLBs on switchOut()
This changeset inserts a TLB flush in BaseCPU::switchOut to prevent stale translations when doing repeated switching. Additionally, the TLB flushing functionality is exported to the Python to make debugging of switching/checkpointing easier. A simulation script will typically use the TLB flushing functionality to generate a reference trace. The following sequence can be used to simulate a handover (this depends on how drain is implemented, but is generally the case) between identically configured CPU models: m5.drain(test_sys) [ cpu.flushTLBs() for cpu in test_sys.cpu ] m5.resume(test_sys) The generated trace should normally be identical to a trace generated when switching between identically configured CPU models or checkpointing and resuming.
This commit is contained in:
parent
964aa49d15
commit
e09e9fa279
4 changed files with 36 additions and 3 deletions
|
@ -114,6 +114,10 @@ class TLB : public BaseTLB
|
||||||
*/
|
*/
|
||||||
TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0,
|
TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0,
|
||||||
bool update_used = true);
|
bool update_used = true);
|
||||||
|
|
||||||
|
/** Remove all entries from the TLB */
|
||||||
|
void flushAll();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Insert a PTE into the TLB. */
|
/** Insert a PTE into the TLB. */
|
||||||
void insert(Addr vpn, int partition_id, int context_id, bool real,
|
void insert(Addr vpn, int partition_id, int context_id, bool real,
|
||||||
|
@ -122,9 +126,6 @@ class TLB : public BaseTLB
|
||||||
/** Given an entry id, read that tlb entries' tag. */
|
/** Given an entry id, read that tlb entries' tag. */
|
||||||
uint64_t TagRead(int entry);
|
uint64_t TagRead(int entry);
|
||||||
|
|
||||||
/** Remove all entries from the TLB */
|
|
||||||
void flushAll();
|
|
||||||
|
|
||||||
/** Remove all non-locked entries from the tlb that match partition id. */
|
/** Remove all non-locked entries from the tlb that match partition id. */
|
||||||
void demapAll(int partition_id);
|
void demapAll(int partition_id);
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@ class BaseCPU(MemObject):
|
||||||
void switchOut();
|
void switchOut();
|
||||||
void takeOverFrom(BaseCPU *cpu);
|
void takeOverFrom(BaseCPU *cpu);
|
||||||
bool switchedOut();
|
bool switchedOut();
|
||||||
|
void flushTLBs();
|
||||||
''')
|
''')
|
||||||
|
|
||||||
def takeOverFrom(self, old_cpu):
|
def takeOverFrom(self, old_cpu):
|
||||||
|
|
|
@ -361,6 +361,10 @@ BaseCPU::switchOut()
|
||||||
_switchedOut = true;
|
_switchedOut = true;
|
||||||
if (profileEvent && profileEvent->scheduled())
|
if (profileEvent && profileEvent->scheduled())
|
||||||
deschedule(profileEvent);
|
deschedule(profileEvent);
|
||||||
|
|
||||||
|
// Flush all TLBs in the CPU to avoid having stale translations if
|
||||||
|
// it gets switched in later.
|
||||||
|
flushTLBs();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -482,6 +486,22 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
|
||||||
getDataPort().bind(data_peer_port);
|
getDataPort().bind(data_peer_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseCPU::flushTLBs()
|
||||||
|
{
|
||||||
|
for (ThreadID i = 0; i < threadContexts.size(); ++i) {
|
||||||
|
ThreadContext &tc(*threadContexts[i]);
|
||||||
|
CheckerCPU *checker(tc.getCheckerCpuPtr());
|
||||||
|
|
||||||
|
tc.getITBPtr()->flushAll();
|
||||||
|
tc.getDTBPtr()->flushAll();
|
||||||
|
if (checker) {
|
||||||
|
checker->getITBPtr()->flushAll();
|
||||||
|
checker->getDTBPtr()->flushAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval)
|
BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval)
|
||||||
: cpu(_cpu), interval(_interval)
|
: cpu(_cpu), interval(_interval)
|
||||||
|
|
|
@ -323,6 +323,17 @@ class BaseCPU : public MemObject
|
||||||
*/
|
*/
|
||||||
virtual void takeOverFrom(BaseCPU *cpu);
|
virtual void takeOverFrom(BaseCPU *cpu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush all TLBs in the CPU.
|
||||||
|
*
|
||||||
|
* This method is mainly used to flush stale translations when
|
||||||
|
* switching CPUs. It is also exported to the Python world to
|
||||||
|
* allow it to request a TLB flush after draining the CPU to make
|
||||||
|
* it easier to compare traces when debugging
|
||||||
|
* handover/checkpointing.
|
||||||
|
*/
|
||||||
|
void flushTLBs();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the CPU is switched out.
|
* Determine if the CPU is switched out.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue