summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorGedare Bloom <gedare@rtems.org>2013-05-21 11:40:11 -0500
committerGedare Bloom <gedare@rtems.org>2013-05-21 11:40:11 -0500
commit22b60c57e697289baa205f11b164f356363c2bee (patch)
tree4206562aae3cdb8b82a3ec8e873f15444502c678 /src/arch
parent30fe807316ebc4b6c37ca522b3cfd6c592ca9003 (diff)
downloadgem5-22b60c57e697289baa205f11b164f356363c2bee.tar.xz
x86: Squash outstanding walks when instructions are squashed.
This is the x86 version of the ARM changeset baa17ba80e06. In case an instruction has been squashed by the o3 cpu, this patch allows page table walker to avoid carrying out a pending translation that the instruction requested for.
Diffstat (limited to 'src/arch')
-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)
{
}
};