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:
Andreas Sandberg 2013-01-07 13:05:48 -05:00
parent 964aa49d15
commit e09e9fa279
4 changed files with 36 additions and 3 deletions

View file

@ -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);

View file

@ -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):

View file

@ -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)

View file

@ -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.
* *