1/* 2 * Copyright (c) 2001-2005 The Regents of The University of Michigan 3 * Copyright (c) 2007 MIPS Technologies, Inc. 4 * Copyright (c) 2007-2008 The Florida State University 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer; 11 * redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution; 14 * neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Authors: Nathan Binkert 31 * Steve Reinhardt 32 * Jaidev Patwardhan 33 * Stephen Hines 34 */ 35 36#include <string> 37#include <vector> 38
| 1/* 2 * Copyright (c) 2001-2005 The Regents of The University of Michigan 3 * Copyright (c) 2007 MIPS Technologies, Inc. 4 * Copyright (c) 2007-2008 The Florida State University 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer; 11 * redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution; 14 * neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Authors: Nathan Binkert 31 * Steve Reinhardt 32 * Jaidev Patwardhan 33 * Stephen Hines 34 */ 35 36#include <string> 37#include <vector> 38
|
| 39#include "arch/arm/faults.hh"
|
39#include "arch/arm/pagetable.hh" 40#include "arch/arm/tlb.hh"
| 40#include "arch/arm/pagetable.hh" 41#include "arch/arm/tlb.hh"
|
41#include "arch/arm/faults.hh"
| |
42#include "arch/arm/utility.hh" 43#include "base/inifile.hh" 44#include "base/str.hh" 45#include "base/trace.hh" 46#include "cpu/thread_context.hh"
| 42#include "arch/arm/utility.hh" 43#include "base/inifile.hh" 44#include "base/str.hh" 45#include "base/trace.hh" 46#include "cpu/thread_context.hh"
|
47#include "sim/process.hh"
| |
48#include "mem/page_table.hh"
| 47#include "mem/page_table.hh"
|
49#include "params/ArmDTB.hh" 50#include "params/ArmITB.hh"
| |
51#include "params/ArmTLB.hh"
| 48#include "params/ArmTLB.hh"
|
52#include "params/ArmUTB.hh"
| 49#include "sim/process.hh"
|
53 54 55using namespace std; 56using namespace ArmISA; 57 58/////////////////////////////////////////////////////////////////////// 59// 60// ARM TLB 61// 62 63#define MODE2MASK(X) (1 << (X)) 64 65TLB::TLB(const Params *p) 66 : BaseTLB(p), size(p->size), nlu(0) 67{ 68 table = new ArmISA::PTE[size]; 69 memset(table, 0, sizeof(ArmISA::PTE[size])); 70 smallPages=0; 71} 72 73TLB::~TLB() 74{ 75 if (table) 76 delete [] table; 77} 78 79// look up an entry in the TLB 80ArmISA::PTE * 81TLB::lookup(Addr vpn, uint8_t asn) const 82{ 83 // assume not found... 84 ArmISA::PTE *retval = NULL; 85 PageTable::const_iterator i = lookupTable.find(vpn); 86 if (i != lookupTable.end()) { 87 while (i->first == vpn) { 88 int index = i->second; 89 ArmISA::PTE *pte = &table[index]; 90 91 /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */ 92 Addr Mask = pte->Mask; 93 Addr InvMask = ~Mask; 94 Addr VPN = pte->VPN; 95 // warn("Valid: %d - %d\n",pte->V0,pte->V1); 96 if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) 97 { // We have a VPN + ASID Match 98 retval = pte; 99 break; 100 } 101 ++i; 102 } 103 } 104 105 DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, 106 retval ? "hit" : "miss", retval ? retval->PFN1 : 0); 107 return retval; 108} 109 110ArmISA::PTE* TLB::getEntry(unsigned Index) const 111{ 112 // Make sure that Index is valid 113 assert(Index<size); 114 return &table[Index]; 115} 116 117int TLB::probeEntry(Addr vpn,uint8_t asn) const 118{ 119 // assume not found... 120 ArmISA::PTE *retval = NULL; 121 int Ind=-1; 122 PageTable::const_iterator i = lookupTable.find(vpn); 123 if (i != lookupTable.end()) { 124 while (i->first == vpn) { 125 int index = i->second; 126 ArmISA::PTE *pte = &table[index]; 127 128 /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */ 129 Addr Mask = pte->Mask; 130 Addr InvMask = ~Mask; 131 Addr VPN = pte->VPN; 132 if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) 133 { // We have a VPN + ASID Match 134 retval = pte; 135 Ind = index; 136 break; 137 } 138 139 ++i; 140 } 141 } 142 DPRINTF(Arm,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind); 143 return Ind; 144} 145Fault inline 146TLB::checkCacheability(RequestPtr &req) 147{ 148 Addr VAddrUncacheable = 0xA0000000; 149 // In ARM, cacheability is controlled by certain bits of the virtual address 150 // or by the TLB entry 151 if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) { 152 // mark request as uncacheable 153 req->setFlags(req->getFlags() | Request::UNCACHEABLE); 154 } 155 return NoFault; 156} 157void TLB::insertAt(ArmISA::PTE &pte, unsigned Index, int _smallPages) 158{ 159 smallPages=_smallPages; 160 if(Index > size){ 161 warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size); 162 } else { 163 // Update TLB 164 DPRINTF(TLB,"TLB[%d]: %x %x %x %x\n",Index,pte.Mask<<11,((pte.VPN << 11) | pte.asid),((pte.PFN0 <<6) | (pte.C0 << 3) | (pte.D0 << 2) | (pte.V0 <<1) | pte.G), 165 ((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G)); 166 if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid 167 PageTable::iterator i = lookupTable.find(table[Index].VPN); 168 lookupTable.erase(i); 169 } 170 table[Index]=pte; 171 // Update fast lookup table 172 lookupTable.insert(make_pair(table[Index].VPN, Index)); 173 // int TestIndex=probeEntry(pte.VPN,pte.asid); 174 // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask); 175 } 176 177} 178 179// insert a new TLB entry 180void 181TLB::insert(Addr addr, ArmISA::PTE &pte) 182{ 183 fatal("TLB Insert not yet implemented\n"); 184} 185 186void 187TLB::flushAll() 188{ 189 DPRINTF(TLB, "flushAll\n"); 190 memset(table, 0, sizeof(ArmISA::PTE[size])); 191 lookupTable.clear(); 192 nlu = 0; 193} 194 195void 196TLB::serialize(ostream &os) 197{ 198 SERIALIZE_SCALAR(size); 199 SERIALIZE_SCALAR(nlu); 200 201 for (int i = 0; i < size; i++) { 202 nameOut(os, csprintf("%s.PTE%d", name(), i)); 203 table[i].serialize(os); 204 } 205} 206 207void 208TLB::unserialize(Checkpoint *cp, const string §ion) 209{ 210 UNSERIALIZE_SCALAR(size); 211 UNSERIALIZE_SCALAR(nlu); 212 213 for (int i = 0; i < size; i++) { 214 table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); 215 if (table[i].V0 || table[i].V1) { 216 lookupTable.insert(make_pair(table[i].VPN, i)); 217 } 218 } 219} 220 221void 222TLB::regStats() 223{ 224 read_hits 225 .name(name() + ".read_hits") 226 .desc("DTB read hits") 227 ; 228 229 read_misses 230 .name(name() + ".read_misses") 231 .desc("DTB read misses") 232 ; 233 234 235 read_accesses 236 .name(name() + ".read_accesses") 237 .desc("DTB read accesses") 238 ; 239 240 write_hits 241 .name(name() + ".write_hits") 242 .desc("DTB write hits") 243 ; 244 245 write_misses 246 .name(name() + ".write_misses") 247 .desc("DTB write misses") 248 ; 249 250 251 write_accesses 252 .name(name() + ".write_accesses") 253 .desc("DTB write accesses") 254 ; 255 256 hits 257 .name(name() + ".hits") 258 .desc("DTB hits") 259 ; 260 261 misses 262 .name(name() + ".misses") 263 .desc("DTB misses") 264 ; 265 266 invalids 267 .name(name() + ".invalids") 268 .desc("DTB access violations") 269 ; 270 271 accesses 272 .name(name() + ".accesses") 273 .desc("DTB accesses") 274 ; 275 276 hits = read_hits + write_hits; 277 misses = read_misses + write_misses; 278 accesses = read_accesses + write_accesses; 279} 280 281Fault
| 50 51 52using namespace std; 53using namespace ArmISA; 54 55/////////////////////////////////////////////////////////////////////// 56// 57// ARM TLB 58// 59 60#define MODE2MASK(X) (1 << (X)) 61 62TLB::TLB(const Params *p) 63 : BaseTLB(p), size(p->size), nlu(0) 64{ 65 table = new ArmISA::PTE[size]; 66 memset(table, 0, sizeof(ArmISA::PTE[size])); 67 smallPages=0; 68} 69 70TLB::~TLB() 71{ 72 if (table) 73 delete [] table; 74} 75 76// look up an entry in the TLB 77ArmISA::PTE * 78TLB::lookup(Addr vpn, uint8_t asn) const 79{ 80 // assume not found... 81 ArmISA::PTE *retval = NULL; 82 PageTable::const_iterator i = lookupTable.find(vpn); 83 if (i != lookupTable.end()) { 84 while (i->first == vpn) { 85 int index = i->second; 86 ArmISA::PTE *pte = &table[index]; 87 88 /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */ 89 Addr Mask = pte->Mask; 90 Addr InvMask = ~Mask; 91 Addr VPN = pte->VPN; 92 // warn("Valid: %d - %d\n",pte->V0,pte->V1); 93 if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) 94 { // We have a VPN + ASID Match 95 retval = pte; 96 break; 97 } 98 ++i; 99 } 100 } 101 102 DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, 103 retval ? "hit" : "miss", retval ? retval->PFN1 : 0); 104 return retval; 105} 106 107ArmISA::PTE* TLB::getEntry(unsigned Index) const 108{ 109 // Make sure that Index is valid 110 assert(Index<size); 111 return &table[Index]; 112} 113 114int TLB::probeEntry(Addr vpn,uint8_t asn) const 115{ 116 // assume not found... 117 ArmISA::PTE *retval = NULL; 118 int Ind=-1; 119 PageTable::const_iterator i = lookupTable.find(vpn); 120 if (i != lookupTable.end()) { 121 while (i->first == vpn) { 122 int index = i->second; 123 ArmISA::PTE *pte = &table[index]; 124 125 /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */ 126 Addr Mask = pte->Mask; 127 Addr InvMask = ~Mask; 128 Addr VPN = pte->VPN; 129 if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) 130 { // We have a VPN + ASID Match 131 retval = pte; 132 Ind = index; 133 break; 134 } 135 136 ++i; 137 } 138 } 139 DPRINTF(Arm,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind); 140 return Ind; 141} 142Fault inline 143TLB::checkCacheability(RequestPtr &req) 144{ 145 Addr VAddrUncacheable = 0xA0000000; 146 // In ARM, cacheability is controlled by certain bits of the virtual address 147 // or by the TLB entry 148 if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) { 149 // mark request as uncacheable 150 req->setFlags(req->getFlags() | Request::UNCACHEABLE); 151 } 152 return NoFault; 153} 154void TLB::insertAt(ArmISA::PTE &pte, unsigned Index, int _smallPages) 155{ 156 smallPages=_smallPages; 157 if(Index > size){ 158 warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size); 159 } else { 160 // Update TLB 161 DPRINTF(TLB,"TLB[%d]: %x %x %x %x\n",Index,pte.Mask<<11,((pte.VPN << 11) | pte.asid),((pte.PFN0 <<6) | (pte.C0 << 3) | (pte.D0 << 2) | (pte.V0 <<1) | pte.G), 162 ((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G)); 163 if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid 164 PageTable::iterator i = lookupTable.find(table[Index].VPN); 165 lookupTable.erase(i); 166 } 167 table[Index]=pte; 168 // Update fast lookup table 169 lookupTable.insert(make_pair(table[Index].VPN, Index)); 170 // int TestIndex=probeEntry(pte.VPN,pte.asid); 171 // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask); 172 } 173 174} 175 176// insert a new TLB entry 177void 178TLB::insert(Addr addr, ArmISA::PTE &pte) 179{ 180 fatal("TLB Insert not yet implemented\n"); 181} 182 183void 184TLB::flushAll() 185{ 186 DPRINTF(TLB, "flushAll\n"); 187 memset(table, 0, sizeof(ArmISA::PTE[size])); 188 lookupTable.clear(); 189 nlu = 0; 190} 191 192void 193TLB::serialize(ostream &os) 194{ 195 SERIALIZE_SCALAR(size); 196 SERIALIZE_SCALAR(nlu); 197 198 for (int i = 0; i < size; i++) { 199 nameOut(os, csprintf("%s.PTE%d", name(), i)); 200 table[i].serialize(os); 201 } 202} 203 204void 205TLB::unserialize(Checkpoint *cp, const string §ion) 206{ 207 UNSERIALIZE_SCALAR(size); 208 UNSERIALIZE_SCALAR(nlu); 209 210 for (int i = 0; i < size; i++) { 211 table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); 212 if (table[i].V0 || table[i].V1) { 213 lookupTable.insert(make_pair(table[i].VPN, i)); 214 } 215 } 216} 217 218void 219TLB::regStats() 220{ 221 read_hits 222 .name(name() + ".read_hits") 223 .desc("DTB read hits") 224 ; 225 226 read_misses 227 .name(name() + ".read_misses") 228 .desc("DTB read misses") 229 ; 230 231 232 read_accesses 233 .name(name() + ".read_accesses") 234 .desc("DTB read accesses") 235 ; 236 237 write_hits 238 .name(name() + ".write_hits") 239 .desc("DTB write hits") 240 ; 241 242 write_misses 243 .name(name() + ".write_misses") 244 .desc("DTB write misses") 245 ; 246 247 248 write_accesses 249 .name(name() + ".write_accesses") 250 .desc("DTB write accesses") 251 ; 252 253 hits 254 .name(name() + ".hits") 255 .desc("DTB hits") 256 ; 257 258 misses 259 .name(name() + ".misses") 260 .desc("DTB misses") 261 ; 262 263 invalids 264 .name(name() + ".invalids") 265 .desc("DTB access violations") 266 ; 267 268 accesses 269 .name(name() + ".accesses") 270 .desc("DTB accesses") 271 ; 272 273 hits = read_hits + write_hits; 274 misses = read_misses + write_misses; 275 accesses = read_accesses + write_accesses; 276} 277 278Fault
|
282ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
| 279TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
|
283{ 284#if !FULL_SYSTEM 285 Process * p = tc->getProcessPtr(); 286 287 Fault fault = p->pTable->translate(req); 288 if(fault != NoFault) 289 return fault; 290 291 return NoFault; 292#else
| 280{ 281#if !FULL_SYSTEM 282 Process * p = tc->getProcessPtr(); 283 284 Fault fault = p->pTable->translate(req); 285 if(fault != NoFault) 286 return fault; 287 288 return NoFault; 289#else
|
293 fatal("ITB translate not yet implemented\n");
| 290 fatal("translate atomic not yet implemented\n");
|
294#endif 295} 296 297void
| 291#endif 292} 293 294void
|
298ITB::translateTiming(RequestPtr req, ThreadContext *tc, 299 Translation *translation)
| 295TLB::translateTiming(RequestPtr req, ThreadContext *tc, 296 Translation *translation, Mode mode)
|
300{ 301 assert(translation);
| 297{ 298 assert(translation);
|
302 translation->finish(translateAtomic(req, tc), req, tc, false);
| 299 translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
|
303} 304
| 300} 301
|
305 306Fault 307DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write) 308{ 309#if !FULL_SYSTEM 310 Process * p = tc->getProcessPtr(); 311 312 Fault fault = p->pTable->translate(req); 313 if(fault != NoFault) 314 return fault; 315 316 return NoFault; 317#else 318 fatal("DTB translate not yet implemented\n"); 319#endif 320} 321 322void 323DTB::translateTiming(RequestPtr req, ThreadContext *tc, 324 Translation *translation, bool write) 325{ 326 assert(translation); 327 translation->finish(translateAtomic(req, tc, write), req, tc, write); 328} 329 330/////////////////////////////////////////////////////////////////////// 331// 332// Arm ITB 333// 334ITB::ITB(const Params *p) 335 : TLB(p) 336{} 337 338 339/////////////////////////////////////////////////////////////////////// 340// 341// Arm DTB 342// 343DTB::DTB(const Params *p) 344 : TLB(p) 345{} 346 347/////////////////////////////////////////////////////////////////////// 348// 349// Arm UTB 350// 351UTB::UTB(const Params *p) 352 : ITB(p), DTB(p) 353{} 354
| |
355ArmISA::PTE & 356TLB::index(bool advance) 357{ 358 ArmISA::PTE *pte = &table[nlu]; 359 360 if (advance) 361 nextnlu(); 362 363 return *pte; 364} 365
| 302ArmISA::PTE & 303TLB::index(bool advance) 304{ 305 ArmISA::PTE *pte = &table[nlu]; 306 307 if (advance) 308 nextnlu(); 309 310 return *pte; 311} 312
|
366ArmISA::ITB * 367ArmITBParams::create()
| 313ArmISA::TLB * 314ArmTLBParams::create()
|
368{
| 315{
|
369 return new ArmISA::ITB(this);
| 316 return new ArmISA::TLB(this);
|
370}
| 317}
|
371 372ArmISA::DTB * 373ArmDTBParams::create() 374{ 375 return new ArmISA::DTB(this); 376} 377 378ArmISA::UTB * 379ArmUTBParams::create() 380{ 381 return new ArmISA::UTB(this); 382}
| |
| |