arm: refactor page table walking
Introduce and use a lookup table. Using fetchDescriptor() rather than DMA cleanly handles nested paging. Change-Id: I69ec762f176bd752ba1040890e731826b58d15a6
This commit is contained in:
parent
09218ed397
commit
8b3434a4f2
2 changed files with 15 additions and 40 deletions
|
@ -65,8 +65,10 @@ TableWalker::TableWalker(const Params *p)
|
||||||
pendingReqs(0),
|
pendingReqs(0),
|
||||||
pendingChangeTick(curTick()),
|
pendingChangeTick(curTick()),
|
||||||
doL1DescEvent(this), doL2DescEvent(this),
|
doL1DescEvent(this), doL2DescEvent(this),
|
||||||
doL0LongDescEvent(this), doL1LongDescEvent(this), doL2LongDescEvent(this),
|
doL0LongDescEvent(this), doL1LongDescEvent(this),
|
||||||
doL3LongDescEvent(this),
|
doL2LongDescEvent(this), doL3LongDescEvent(this),
|
||||||
|
LongDescEventByLevel { &doL0LongDescEvent, &doL1LongDescEvent,
|
||||||
|
&doL2LongDescEvent, &doL3LongDescEvent },
|
||||||
doProcessEvent(this)
|
doProcessEvent(this)
|
||||||
{
|
{
|
||||||
sctlr = 0;
|
sctlr = 0;
|
||||||
|
@ -138,7 +140,8 @@ void
|
||||||
TableWalker::completeDrain()
|
TableWalker::completeDrain()
|
||||||
{
|
{
|
||||||
if (drainState() == DrainState::Draining &&
|
if (drainState() == DrainState::Draining &&
|
||||||
stateQueues[L1].empty() && stateQueues[L2].empty() &&
|
stateQueues[L0].empty() && stateQueues[L1].empty() &&
|
||||||
|
stateQueues[L2].empty() && stateQueues[L3].empty() &&
|
||||||
pendingQueue.empty()) {
|
pendingQueue.empty()) {
|
||||||
|
|
||||||
DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
|
DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
|
||||||
|
@ -697,12 +700,10 @@ TableWalker::processWalkLPAE()
|
||||||
currState->longDesc.aarch64 = false;
|
currState->longDesc.aarch64 = false;
|
||||||
currState->longDesc.grainSize = Grain4KB;
|
currState->longDesc.grainSize = Grain4KB;
|
||||||
|
|
||||||
Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent
|
|
||||||
: (Event *) &doL2LongDescEvent;
|
|
||||||
|
|
||||||
bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
|
bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
|
||||||
sizeof(uint64_t), flag, start_lookup_level,
|
sizeof(uint64_t), flag, start_lookup_level,
|
||||||
event, &TableWalker::doLongDescriptor);
|
LongDescEventByLevel[start_lookup_level],
|
||||||
|
&TableWalker::doLongDescriptor);
|
||||||
if (!delayed) {
|
if (!delayed) {
|
||||||
f = currState->fault;
|
f = currState->fault;
|
||||||
}
|
}
|
||||||
|
@ -967,32 +968,9 @@ TableWalker::processWalkAArch64()
|
||||||
currState->longDesc.grainSize = tg;
|
currState->longDesc.grainSize = tg;
|
||||||
|
|
||||||
if (currState->timing) {
|
if (currState->timing) {
|
||||||
Event *event;
|
fetchDescriptor(desc_addr, (uint8_t*) &currState->longDesc.data,
|
||||||
switch (start_lookup_level) {
|
sizeof(uint64_t), flag, start_lookup_level,
|
||||||
case L0:
|
LongDescEventByLevel[start_lookup_level], NULL);
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
|
fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
|
||||||
sizeof(uint64_t), flag, -1, NULL,
|
sizeof(uint64_t), flag, -1, NULL,
|
||||||
|
@ -1672,19 +1650,15 @@ TableWalker::doLongDescriptor()
|
||||||
if (currState->secureLookup)
|
if (currState->secureLookup)
|
||||||
flag.set(Request::SECURE);
|
flag.set(Request::SECURE);
|
||||||
|
|
||||||
currState->longDesc.lookupLevel =
|
LookupLevel L = currState->longDesc.lookupLevel =
|
||||||
(LookupLevel) (currState->longDesc.lookupLevel + 1);
|
(LookupLevel) (currState->longDesc.lookupLevel + 1);
|
||||||
Event *event = NULL;
|
Event *event = NULL;
|
||||||
switch (currState->longDesc.lookupLevel) {
|
switch (L) {
|
||||||
case L1:
|
case L1:
|
||||||
assert(currState->aarch64);
|
assert(currState->aarch64);
|
||||||
event = &doL1LongDescEvent;
|
|
||||||
break;
|
|
||||||
case L2:
|
case L2:
|
||||||
event = &doL2LongDescEvent;
|
|
||||||
break;
|
|
||||||
case L3:
|
case L3:
|
||||||
event = &doL3LongDescEvent;
|
event = LongDescEventByLevel[L];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Wrong lookup level in table walk\n");
|
panic("Wrong lookup level in table walk\n");
|
||||||
|
|
|
@ -944,6 +944,7 @@ class TableWalker : public MemObject
|
||||||
&TableWalker::doL3LongDescriptorWrapper> doL3LongDescEvent;
|
&TableWalker::doL3LongDescriptorWrapper> doL3LongDescEvent;
|
||||||
|
|
||||||
void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
|
void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
|
||||||
|
Event* LongDescEventByLevel[4];
|
||||||
|
|
||||||
bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
|
bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
|
||||||
Request::Flags flags, int queueIndex, Event *event,
|
Request::Flags flags, int queueIndex, Event *event,
|
||||||
|
|
Loading…
Reference in a new issue