summaryrefslogtreecommitdiff
path: root/src/arch/arm/table_walker.cc
diff options
context:
space:
mode:
authorCurtis Dunham <Curtis.Dunham@arm.com>2016-08-02 10:38:03 +0100
committerCurtis Dunham <Curtis.Dunham@arm.com>2016-08-02 10:38:03 +0100
commit8b3434a4f2090961dc5b3da7bc48b8b636b9f1e3 (patch)
tree07e1633a0d9d28ffe5940260e48e81ae7df8fc1b /src/arch/arm/table_walker.cc
parent09218ed397f0df12dd7d4cd21dd6203330e69d06 (diff)
downloadgem5-8b3434a4f2090961dc5b3da7bc48b8b636b9f1e3.tar.xz
arm: refactor page table walking
Introduce and use a lookup table. Using fetchDescriptor() rather than DMA cleanly handles nested paging. Change-Id: I69ec762f176bd752ba1040890e731826b58d15a6
Diffstat (limited to 'src/arch/arm/table_walker.cc')
-rw-r--r--src/arch/arm/table_walker.cc54
1 files changed, 14 insertions, 40 deletions
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index 1f06d009a..82462ab33 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -65,8 +65,10 @@ TableWalker::TableWalker(const Params *p)
pendingReqs(0),
pendingChangeTick(curTick()),
doL1DescEvent(this), doL2DescEvent(this),
- doL0LongDescEvent(this), doL1LongDescEvent(this), doL2LongDescEvent(this),
- doL3LongDescEvent(this),
+ doL0LongDescEvent(this), doL1LongDescEvent(this),
+ doL2LongDescEvent(this), doL3LongDescEvent(this),
+ LongDescEventByLevel { &doL0LongDescEvent, &doL1LongDescEvent,
+ &doL2LongDescEvent, &doL3LongDescEvent },
doProcessEvent(this)
{
sctlr = 0;
@@ -138,7 +140,8 @@ void
TableWalker::completeDrain()
{
if (drainState() == DrainState::Draining &&
- stateQueues[L1].empty() && stateQueues[L2].empty() &&
+ stateQueues[L0].empty() && stateQueues[L1].empty() &&
+ stateQueues[L2].empty() && stateQueues[L3].empty() &&
pendingQueue.empty()) {
DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
@@ -697,12 +700,10 @@ TableWalker::processWalkLPAE()
currState->longDesc.aarch64 = false;
currState->longDesc.grainSize = Grain4KB;
- Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent
- : (Event *) &doL2LongDescEvent;
-
bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
sizeof(uint64_t), flag, start_lookup_level,
- event, &TableWalker::doLongDescriptor);
+ LongDescEventByLevel[start_lookup_level],
+ &TableWalker::doLongDescriptor);
if (!delayed) {
f = currState->fault;
}
@@ -967,32 +968,9 @@ TableWalker::processWalkAArch64()
currState->longDesc.grainSize = tg;
if (currState->timing) {
- Event *event;
- switch (start_lookup_level) {
- case L0:
- event = (Event *) &doL0LongDescEvent;
- break;
- case L1:
- event = (Event *) &doL1LongDescEvent;
- break;
- case L2:
- event = (Event *) &doL2LongDescEvent;
- break;
- case L3:
- event = (Event *) &doL3LongDescEvent;
- break;
- default:
- panic("Invalid table lookup level");
- break;
- }
- port->dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t),
- event, (uint8_t*) &currState->longDesc.data,
- currState->tc->getCpuPtr()->clockPeriod(), flag);
- DPRINTF(TLBVerbose,
- "Adding to walker fifo: queue size before adding: %d\n",
- stateQueues[start_lookup_level].size());
- stateQueues[start_lookup_level].push_back(currState);
- currState = NULL;
+ fetchDescriptor(desc_addr, (uint8_t*) &currState->longDesc.data,
+ sizeof(uint64_t), flag, start_lookup_level,
+ LongDescEventByLevel[start_lookup_level], NULL);
} else {
fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
sizeof(uint64_t), flag, -1, NULL,
@@ -1672,19 +1650,15 @@ TableWalker::doLongDescriptor()
if (currState->secureLookup)
flag.set(Request::SECURE);
- currState->longDesc.lookupLevel =
+ LookupLevel L = currState->longDesc.lookupLevel =
(LookupLevel) (currState->longDesc.lookupLevel + 1);
Event *event = NULL;
- switch (currState->longDesc.lookupLevel) {
+ switch (L) {
case L1:
assert(currState->aarch64);
- event = &doL1LongDescEvent;
- break;
case L2:
- event = &doL2LongDescEvent;
- break;
case L3:
- event = &doL3LongDescEvent;
+ event = LongDescEventByLevel[L];
break;
default:
panic("Wrong lookup level in table walk\n");