arm: refactor page table walking
authorCurtis Dunham <Curtis.Dunham@arm.com>
Tue, 2 Aug 2016 09:38:03 +0000 (10:38 +0100)
committerCurtis Dunham <Curtis.Dunham@arm.com>
Tue, 2 Aug 2016 09:38:03 +0000 (10:38 +0100)
Introduce and use a lookup table.

Using fetchDescriptor() rather than DMA cleanly handles nested paging.

Change-Id: I69ec762f176bd752ba1040890e731826b58d15a6

src/arch/arm/table_walker.cc
src/arch/arm/table_walker.hh

index 1f06d009a24e9f9808e32c707e812d6eb0c49edc..82462ab3343481ac3d3a9a0f78bfebf18563b1a9 100644 (file)
@@ -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");
index fc628f714ab78adeb2b95c018c2e9fc5cd82f8cc..c52cfcb4c9ed1ca4b0cea017eaaf39ee5368d7bb 100644 (file)
@@ -944,6 +944,7 @@ class TableWalker : public MemObject
                  &TableWalker::doL3LongDescriptorWrapper> doL3LongDescEvent;
 
     void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
+    Event* LongDescEventByLevel[4];
 
     bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
         Request::Flags flags, int queueIndex, Event *event,