1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 27 unchanged lines hidden (view full) --- 36 * 37 * Authors: Ali Saidi 38 */ 39 40#include "arch/arm/faults.hh" 41#include "arch/arm/table_walker.hh" 42#include "arch/arm/tlb.hh" 43#include "dev/io_device.hh" |
44#include "cpu/base.hh" |
45#include "cpu/thread_context.hh" 46 47using namespace ArmISA; 48 49TableWalker::TableWalker(const Params *p) |
50 : MemObject(p), port(NULL), tlb(NULL), currState(NULL), pending(false), 51 doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this) |
52{ 53 sctlr = 0; 54} 55 56TableWalker::~TableWalker() 57{ 58 ; 59} --- 51 unchanged lines hidden (view full) --- 111 currState->vaddr = currState->req->getVaddr(); 112 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR); 113 sctlr = currState->sctlr; 114 currState->N = currState->tc->readMiscReg(MISCREG_TTBCR); 115 116 currState->isFetch = (currState->mode == TLB::Execute); 117 currState->isWrite = (currState->mode == TLB::Write); 118 |
119 120 if (!currState->timing) 121 return processWalk(); 122 123 if (pending) { 124 pendingQueue.push_back(currState); 125 currState = NULL; 126 } else { 127 pending = true; 128 processWalk(); 129 } 130 131 return NoFault; 132} 133 134void 135TableWalker::processWalkWrapper() 136{ 137 assert(!currState); 138 assert(pendingQueue.size()); 139 currState = pendingQueue.front(); 140 pendingQueue.pop_front(); 141 pending = true; 142 processWalk(); 143} 144 145Fault 146TableWalker::processWalk() 147{ |
148 Addr ttbr = 0; 149 150 // If translation isn't enabled, we shouldn't be here 151 assert(currState->sctlr.m); 152 153 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n", 154 currState->vaddr, currState->N, mbits(currState->vaddr, 31, 155 32-currState->N)); --- 15 unchanged lines hidden (view full) --- 171 // Trickbox address check 172 Fault f; 173 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t), 174 currState->isFetch, currState->isWrite, 0, true); 175 if (f) { 176 if (currState->timing) { 177 currState->transState->finish(f, currState->req, 178 currState->tc, currState->mode); |
179 180 pending = false; 181 nextWalk(currState->tc); |
182 currState = NULL; 183 } else { 184 currState->tc = NULL; 185 currState->req = NULL; 186 } 187 return f; 188 } 189 190 if (currState->timing) { 191 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), |
192 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data, 193 currState->tc->getCpuPtr()->ticks(1)); |
194 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 195 stateQueueL1.size()); 196 stateQueueL1.push_back(currState); 197 currState = NULL; 198 } else { 199 Request::Flags flag = 0; 200 if (currState->sctlr.c == 0){ 201 flag = Request::UNCACHEABLE; 202 } 203 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), |
204 NULL, (uint8_t*)&currState->l1Desc.data, 205 currState->tc->getCpuPtr()->ticks(1), flag); |
206 doL1Descriptor(); 207 f = currState->fault; 208 } 209 210 return f; 211} 212 213void --- 314 unchanged lines hidden (view full) --- 528 } 529 return; 530 } 531 532 533 if (currState->timing) { 534 currState->delayed = true; 535 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), |
536 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, 537 currState->tc->getCpuPtr()->ticks(1)); |
538 } else { 539 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), |
540 NULL, (uint8_t*)&currState->l2Desc.data, 541 currState->tc->getCpuPtr()->ticks(1)); |
542 doL2Descriptor(); 543 } 544 return; 545 default: 546 panic("A new type in a 2 bit field?\n"); 547 } 548} 549 --- 71 unchanged lines hidden (view full) --- 621 doL1Descriptor(); 622 623 stateQueueL1.pop_front(); 624 // Check if fault was generated 625 if (currState->fault != NoFault) { 626 currState->transState->finish(currState->fault, currState->req, 627 currState->tc, currState->mode); 628 |
629 pending = false; 630 nextWalk(currState->tc); 631 |
632 currState->req = NULL; 633 currState->tc = NULL; 634 currState->delayed = false; 635 636 } 637 else if (!currState->delayed) { 638 // delay is not set so there is no L2 to do 639 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 640 currState->fault = tlb->translateTiming(currState->req, currState->tc, 641 currState->transState, currState->mode); 642 |
643 pending = false; 644 nextWalk(currState->tc); 645 |
646 currState->req = NULL; 647 currState->tc = NULL; 648 currState->delayed = false; |
649 delete currState; 650 } else { 651 // need to do L2 descriptor 652 stateQueueL2.push_back(currState); 653 } 654 currState = NULL; 655} 656 --- 13 unchanged lines hidden (view full) --- 670 currState->tc, currState->mode); 671 } 672 else { 673 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 674 currState->fault = tlb->translateTiming(currState->req, currState->tc, 675 currState->transState, currState->mode); 676 } 677 |
678 679 stateQueueL2.pop_front(); 680 pending = false; 681 nextWalk(currState->tc); 682 |
683 currState->req = NULL; 684 currState->tc = NULL; 685 currState->delayed = false; 686 |
687 delete currState; 688 currState = NULL; 689} 690 |
691void 692TableWalker::nextWalk(ThreadContext *tc) 693{ 694 if (pendingQueue.size()) 695 schedule(doProcessEvent, tc->getCpuPtr()->nextCycle(curTick+1)); 696} 697 698 699 |
700ArmISA::TableWalker * 701ArmTableWalkerParams::create() 702{ 703 return new ArmISA::TableWalker(this); 704} 705 |