summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/X86TLB.py2
-rw-r--r--src/arch/x86/pagetable_walker.cc37
-rw-r--r--src/arch/x86/pagetable_walker.hh10
3 files changed, 43 insertions, 6 deletions
diff --git a/src/arch/x86/X86TLB.py b/src/arch/x86/X86TLB.py
index a08dbb138..b652118ce 100644
--- a/src/arch/x86/X86TLB.py
+++ b/src/arch/x86/X86TLB.py
@@ -47,6 +47,8 @@ class X86PagetableWalker(MemObject):
cxx_header = 'arch/x86/pagetable_walker.hh'
port = MasterPort("Port for the hardware table walker")
system = Param.System(Parent.any, "system object")
+ num_squash_per_cycle = Param.Unsigned(4,
+ "Number of outstanding walks that can be squashed per cycle")
class X86TLB(BaseTLB):
type = 'X86TLB'
diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc
index 853e062e7..45f902999 100644
--- a/src/arch/x86/pagetable_walker.cc
+++ b/src/arch/x86/pagetable_walker.cc
@@ -139,11 +139,8 @@ Walker::recvTimingResp(PacketPtr pkt)
delete senderWalk;
// Since we block requests when another is outstanding, we
// need to check if there is a waiting request to be serviced
- if (currStates.size()) {
- WalkerState * newState = currStates.front();
- if (!newState->wasStarted())
- newState->startWalk();
- }
+ if (currStates.size())
+ startWalkWrapper();
}
return true;
}
@@ -192,6 +189,36 @@ Walker::WalkerState::initState(ThreadContext * _tc,
timing = _isTiming;
}
+void
+Walker::startWalkWrapper()
+{
+ unsigned num_squashed = 0;
+ WalkerState *currState = currStates.front();
+ while ((num_squashed < numSquashable) && currState &&
+ currState->translation->squashed()) {
+ currStates.pop_front();
+ num_squashed++;
+
+ DPRINTF(PageTableWalker, "Squashing table walk for address %#x\n",
+ currState->req->getVaddr());
+
+ // finish the translation which will delete the translation object
+ currState->translation->finish(new UnimpFault("Squashed Inst"),
+ currState->req, currState->tc, currState->mode);
+
+ // delete the current request
+ delete currState;
+
+ // check the next translation request, if it exists
+ if (currStates.size())
+ currState = currStates.front();
+ else
+ currState = NULL;
+ }
+ if (currState && !currState->wasStarted())
+ currState->startWalk();
+}
+
Fault
Walker::WalkerState::startWalk()
{
diff --git a/src/arch/x86/pagetable_walker.hh b/src/arch/x86/pagetable_walker.hh
index c2781ca1b..c6766689b 100644
--- a/src/arch/x86/pagetable_walker.hh
+++ b/src/arch/x86/pagetable_walker.hh
@@ -87,6 +87,7 @@ namespace X86ISA
// State to track each walk of the page table
class WalkerState
{
+ friend class Walker;
private:
enum State {
Ready,
@@ -176,6 +177,12 @@ namespace X86ISA
System * sys;
MasterID masterId;
+ // The number of outstanding walks that can be squashed per cycle.
+ unsigned numSquashable;
+
+ // Wrapper for checking for squashes before starting a translation.
+ void startWalkWrapper();
+
// Functions for dealing with packets.
bool recvTimingResp(PacketPtr pkt);
void recvRetry();
@@ -199,7 +206,8 @@ namespace X86ISA
Walker(const Params *params) :
MemObject(params), port(name() + ".port", this),
funcState(this, NULL, NULL, true), tlb(NULL), sys(params->system),
- masterId(sys->getMasterId(name()))
+ masterId(sys->getMasterId(name())),
+ numSquashable(params->num_squash_per_cycle)
{
}
};