1/* |
2 * Copyright (c) 2010, 2012-2015 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 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated --- 40 unchanged lines hidden (view full) --- 51#include "debug/Drain.hh" 52#include "debug/TLB.hh" 53#include "debug/TLBVerbose.hh" 54#include "sim/system.hh" 55 56using namespace ArmISA; 57 58TableWalker::TableWalker(const Params *p) |
59 : MemObject(p), drainManager(NULL), 60 stage2Mmu(NULL), port(NULL), masterId(Request::invldMasterId), 61 isStage2(p->is_stage2), tlb(NULL), 62 currState(NULL), pending(false), |
63 numSquashable(p->num_squash_per_cycle), 64 pendingReqs(0), 65 pendingChangeTick(curTick()), 66 doL1DescEvent(this), doL2DescEvent(this), 67 doL0LongDescEvent(this), doL1LongDescEvent(this), doL2LongDescEvent(this), 68 doL3LongDescEvent(this), 69 doProcessEvent(this) 70{ 71 sctlr = 0; 72 73 // Cache system-level properties 74 if (FullSystem) { |
75 ArmSystem *armSys = dynamic_cast<ArmSystem *>(p->sys); |
76 assert(armSys); 77 haveSecurity = armSys->haveSecurity(); 78 _haveLPAE = armSys->haveLPAE(); 79 _haveVirtualization = armSys->haveVirtualization(); 80 physAddrRange = armSys->physAddrRange(); 81 _haveLargeAsid64 = armSys->haveLargeAsid64(); 82 } else { |
83 haveSecurity = _haveLPAE = _haveVirtualization = false; 84 _haveLargeAsid64 = false; 85 physAddrRange = 32; 86 } 87 88} 89 90TableWalker::~TableWalker() 91{ 92 ; 93} 94 |
95void 96TableWalker::setMMU(Stage2MMU *m, MasterID master_id) 97{ 98 stage2Mmu = m; 99 port = &m->getPort(); 100 masterId = master_id; 101} 102 103void 104TableWalker::init() 105{ 106 fatal_if(!stage2Mmu, "Table walker must have a valid stage-2 MMU\n"); 107 fatal_if(!port, "Table walker must have a valid port\n"); 108 fatal_if(!tlb, "Table walker must have a valid TLB\n"); 109} 110 111BaseMasterPort& 112TableWalker::getMasterPort(const std::string &if_name, PortID idx) 113{ 114 if (if_name == "port") { 115 if (!isStage2) { 116 return *port; 117 } else { 118 fatal("Cannot access table walker port through stage-two walker\n"); 119 } 120 } 121 return MemObject::getMasterPort(if_name, idx); 122} 123 |
124TableWalker::WalkerState::WalkerState() : 125 tc(nullptr), aarch64(false), el(EL0), physAddrRange(0), req(nullptr), 126 asid(0), vmid(0), isHyp(false), transState(nullptr), 127 vaddr(0), vaddr_tainted(0), isWrite(false), isFetch(false), isSecure(false), 128 secureLookup(false), rwTable(false), userTable(false), xnTable(false), 129 pxnTable(false), stage2Req(false), doingStage2(false), 130 stage2Tran(nullptr), timing(false), functional(false), 131 mode(BaseTLB::Read), tranType(TLB::NormalTran), l2Desc(l1Desc), --- 11 unchanged lines hidden (view full) --- 143 drainManager->signalDrainDone(); 144 drainManager = NULL; 145 } 146} 147 148unsigned int 149TableWalker::drain(DrainManager *dm) 150{ |
151 bool state_queues_not_empty = false; 152 153 for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) { 154 if (!stateQueues[i].empty()) { 155 state_queues_not_empty = true; 156 break; 157 } 158 } 159 160 if (state_queues_not_empty || pendingQueue.size()) { 161 drainManager = dm; 162 setDrainState(Drainable::Draining); 163 DPRINTF(Drain, "TableWalker not drained\n"); 164 165 // return port drain count plus the table walker itself needs to drain |
166 return 1; |
167 } else { 168 setDrainState(Drainable::Drained); 169 DPRINTF(Drain, "TableWalker free, no need to drain\n"); 170 171 // table walker is drained, but its ports may still need to be drained |
172 return 0; |
173 } 174} 175 176void 177TableWalker::drainResume() 178{ 179 Drainable::drainResume(); 180 if (params()->sys->isTimingMode() && currState) { 181 delete currState; 182 currState = NULL; 183 pendingChange(); 184 } 185} 186 |
187Fault 188TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid, 189 uint8_t _vmid, bool _isHyp, TLB::Mode _mode, 190 TLB::Translation *_trans, bool _timing, bool _functional, 191 bool secure, TLB::ArmTranslationType tranType) 192{ 193 assert(!(_functional && _timing)); 194 ++statWalks; --- 764 unchanged lines hidden (view full) --- 959 break; 960 case L3: 961 event = (Event *) &doL3LongDescEvent; 962 break; 963 default: 964 panic("Invalid table lookup level"); 965 break; 966 } |
967 port->dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), |
968 event, (uint8_t*) &currState->longDesc.data, 969 currState->tc->getCpuPtr()->clockPeriod(), flag); 970 DPRINTF(TLBVerbose, 971 "Adding to walker fifo: queue size before adding: %d\n", 972 stateQueues[start_lookup_level].size()); 973 stateQueues[start_lookup_level].push_back(currState); 974 currState = NULL; 975 } else if (!currState->functional) { |
976 port->dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), |
977 NULL, (uint8_t*) &currState->longDesc.data, 978 currState->tc->getCpuPtr()->clockPeriod(), flag); 979 doLongDescriptor(); 980 f = currState->fault; 981 } else { 982 RequestPtr req = new Request(desc_addr, sizeof(uint64_t), flag, 983 masterId); 984 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 985 pkt->dataStatic((uint8_t*) &currState->longDesc.data); |
986 port->sendFunctional(pkt); |
987 doLongDescriptor(); 988 delete req; 989 delete pkt; 990 f = currState->fault; 991 } 992 993 return f; 994} --- 934 unchanged lines hidden (view full) --- 1929 flags = flags | TLB::MustBeOne; 1930 1931 if (isTiming) { 1932 Stage2MMU::Stage2Translation *tran = new 1933 Stage2MMU::Stage2Translation(*stage2Mmu, data, event, 1934 currState->vaddr); 1935 currState->stage2Tran = tran; 1936 stage2Mmu->readDataTimed(currState->tc, descAddr, tran, numBytes, |
1937 flags); |
1938 fault = tran->fault; 1939 } else { 1940 fault = stage2Mmu->readDataUntimed(currState->tc, |
1941 currState->vaddr, descAddr, data, numBytes, flags, |
1942 currState->functional); 1943 } 1944 1945 if (fault != NoFault) { 1946 currState->fault = fault; 1947 } 1948 if (isTiming) { 1949 if (queueIndex >= 0) { 1950 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 1951 stateQueues[queueIndex].size()); 1952 stateQueues[queueIndex].push_back(currState); 1953 currState = NULL; 1954 } 1955 } else { 1956 (this->*doDescriptor)(); 1957 } 1958 } else { 1959 if (isTiming) { |
1960 port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, event, data, |
1961 currState->tc->getCpuPtr()->clockPeriod(),flags); 1962 if (queueIndex >= 0) { 1963 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 1964 stateQueues[queueIndex].size()); 1965 stateQueues[queueIndex].push_back(currState); 1966 currState = NULL; 1967 } 1968 } else if (!currState->functional) { |
1969 port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, NULL, data, |
1970 currState->tc->getCpuPtr()->clockPeriod(), flags); 1971 (this->*doDescriptor)(); 1972 } else { 1973 RequestPtr req = new Request(descAddr, numBytes, flags, masterId); 1974 req->taskId(ContextSwitchTaskId::DMA); 1975 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 1976 pkt->dataStatic(data); |
1977 port->sendFunctional(pkt); |
1978 (this->*doDescriptor)(); 1979 delete req; 1980 delete pkt; 1981 } 1982 } 1983 return (isTiming); 1984} 1985 --- 237 unchanged lines hidden --- |