1/* 2 * Copyright (c) 2001-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ali Saidi 29 */ 30 31#include "arch/sparc/asi.hh" 32#include "arch/sparc/miscregfile.hh" 33#include "arch/sparc/tlb.hh"
| 1/* 2 * Copyright (c) 2001-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ali Saidi 29 */ 30 31#include "arch/sparc/asi.hh" 32#include "arch/sparc/miscregfile.hh" 33#include "arch/sparc/tlb.hh"
|
| 34#include "base/bitfield.hh"
|
34#include "base/trace.hh" 35#include "cpu/thread_context.hh" 36#include "cpu/base.hh" 37#include "mem/packet_access.hh" 38#include "mem/request.hh" 39#include "sim/builder.hh" 40 41/* @todo remove some of the magic constants. -- ali 42 * */ 43namespace SparcISA 44{ 45 46TLB::TLB(const std::string &name, int s) 47 : SimObject(name), size(s) 48{ 49 // To make this work you'll have to change the hypervisor and OS 50 if (size > 64) 51 fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); 52 53 tlb = new TlbEntry[size]; 54 memset(tlb, 0, sizeof(TlbEntry) * size); 55} 56 57void 58TLB::clearUsedBits() 59{ 60 MapIter i; 61 for (i = lookupTable.begin(); i != lookupTable.end();) { 62 TlbEntry *t = i->second; 63 if (!t->pte.locked()) { 64 t->used = false; 65 usedEntries--; 66 } 67 } 68} 69 70 71void 72TLB::insert(Addr va, int partition_id, int context_id, bool real, 73 const PageTableEntry& PTE) 74{ 75 76 77 MapIter i; 78 TlbEntry *new_entry; 79 80 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x, pid=%d cid=%d r=%d\n", 81 va, partition_id, context_id, (int)real); 82 83 int x = -1; 84 for (x = 0; x < size; x++) { 85 if (!tlb[x].valid || !tlb[x].used) { 86 new_entry = &tlb[x]; 87 break; 88 } 89 } 90 91 // Update the last ently if their all locked 92 if (x == -1) 93 x = size - 1; 94 95 assert(PTE.valid()); 96 new_entry->range.va = va; 97 new_entry->range.size = PTE.size(); 98 new_entry->range.partitionId = partition_id; 99 new_entry->range.contextId = context_id; 100 new_entry->range.real = real; 101 new_entry->pte = PTE; 102 new_entry->used = true;; 103 new_entry->valid = true; 104 usedEntries++; 105 106 107 // Demap any entry that conflicts 108 i = lookupTable.find(new_entry->range); 109 if (i != lookupTable.end()) { 110 i->second->valid = false; 111 if (i->second->used) { 112 i->second->used = false; 113 usedEntries--; 114 } 115 DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n"); 116 lookupTable.erase(i); 117 } 118 119 lookupTable.insert(new_entry->range, new_entry);; 120 121 // If all entries have there used bit set, clear it on them all, but the 122 // one we just inserted 123 if (usedEntries == size) { 124 clearUsedBits(); 125 new_entry->used = true; 126 usedEntries++; 127 } 128 129} 130 131 132TlbEntry* 133TLB::lookup(Addr va, int partition_id, bool real, int context_id) 134{ 135 MapIter i; 136 TlbRange tr; 137 TlbEntry *t; 138 139 DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n", 140 va, partition_id, context_id, real); 141 // Assemble full address structure 142 tr.va = va; 143 tr.size = va + MachineBytes; 144 tr.contextId = context_id; 145 tr.partitionId = partition_id; 146 tr.real = real; 147 148 // Try to find the entry 149 i = lookupTable.find(tr); 150 if (i == lookupTable.end()) { 151 DPRINTF(TLB, "TLB: No valid entry found\n"); 152 return NULL; 153 } 154 DPRINTF(TLB, "TLB: Valid entry found\n"); 155 156 // Mark the entries used bit and clear other used bits in needed 157 t = i->second; 158 if (!t->used) { 159 t->used = true; 160 usedEntries++; 161 if (usedEntries == size) { 162 clearUsedBits(); 163 t->used = true; 164 usedEntries++; 165 } 166 } 167 168 return t; 169} 170 171 172void 173TLB::demapPage(Addr va, int partition_id, bool real, int context_id) 174{ 175 TlbRange tr; 176 MapIter i; 177 178 // Assemble full address structure 179 tr.va = va; 180 tr.size = va + MachineBytes; 181 tr.contextId = context_id; 182 tr.partitionId = partition_id; 183 tr.real = real; 184 185 // Demap any entry that conflicts 186 i = lookupTable.find(tr); 187 if (i != lookupTable.end()) { 188 i->second->valid = false; 189 if (i->second->used) { 190 i->second->used = false; 191 usedEntries--; 192 } 193 lookupTable.erase(i); 194 } 195} 196 197void 198TLB::demapContext(int partition_id, int context_id) 199{ 200 int x; 201 for (x = 0; x < size; x++) { 202 if (tlb[x].range.contextId == context_id && 203 tlb[x].range.partitionId == partition_id) { 204 tlb[x].valid = false; 205 if (tlb[x].used) { 206 tlb[x].used = false; 207 usedEntries--; 208 } 209 lookupTable.erase(tlb[x].range); 210 } 211 } 212} 213 214void 215TLB::demapAll(int partition_id) 216{ 217 int x; 218 for (x = 0; x < size; x++) { 219 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { 220 tlb[x].valid = false; 221 if (tlb[x].used) { 222 tlb[x].used = false; 223 usedEntries--; 224 } 225 lookupTable.erase(tlb[x].range); 226 } 227 } 228} 229 230void 231TLB::invalidateAll() 232{ 233 int x; 234 for (x = 0; x < size; x++) { 235 tlb[x].valid = false; 236 } 237 usedEntries = 0; 238} 239 240uint64_t 241TLB::TteRead(int entry) { 242 assert(entry < size); 243 return tlb[entry].pte(); 244} 245 246uint64_t 247TLB::TagRead(int entry) { 248 assert(entry < size); 249 uint64_t tag; 250 251 tag = tlb[entry].range.contextId | tlb[entry].range.va | 252 (uint64_t)tlb[entry].range.partitionId << 61; 253 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 254 tag |= (uint64_t)~tlb[entry].pte._size() << 56; 255 return tag; 256} 257 258bool 259TLB::validVirtualAddress(Addr va, bool am) 260{ 261 if (am) 262 return true; 263 if (va >= StartVAddrHole && va <= EndVAddrHole) 264 return false; 265 return true; 266} 267 268void 269TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, 270 bool se, FaultTypes ft, int asi) 271{ 272 uint64_t sfsr; 273 sfsr = tc->readMiscReg(reg); 274 275 if (sfsr & 0x1) 276 sfsr = 0x3; 277 else 278 sfsr = 1; 279 280 if (write) 281 sfsr |= 1 << 2; 282 sfsr |= ct << 4; 283 if (se) 284 sfsr |= 1 << 6; 285 sfsr |= ft << 7; 286 sfsr |= asi << 16; 287 tc->setMiscReg(reg, sfsr); 288} 289 290 291void 292ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct, 293 bool se, FaultTypes ft, int asi) 294{ 295 DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n", 296 (int)write, ct, ft, asi); 297 TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi); 298} 299 300void 301DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, 302 bool se, FaultTypes ft, int asi) 303{ 304 DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", 305 a, (int)write, ct, ft, asi); 306 TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); 307 tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a); 308} 309 310 311Fault 312ITB::translate(RequestPtr &req, ThreadContext *tc) 313{ 314 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 315 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 316 bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1; 317 uint64_t tl = tc->readMiscReg(MISCREG_TL); 318 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 319 bool addr_mask = pstate >> 3 & 0x1; 320 bool priv = pstate >> 2 & 0x1; 321 Addr vaddr = req->getVaddr(); 322 int context; 323 ContextType ct; 324 int asi; 325 bool real = false; 326 TlbEntry *e; 327 328 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n", 329 vaddr, req->getSize()); 330 331 assert(req->getAsi() == ASI_IMPLICIT); 332 333 if (tl > 0) { 334 asi = ASI_N; 335 ct = Nucleus; 336 context = 0; 337 } else { 338 asi = ASI_P; 339 ct = Primary; 340 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 341 } 342 343 if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) { 344 req->setPaddr(req->getVaddr() & PAddrImplMask); 345 return NoFault; 346 } 347 348 // If the asi is unaligned trap 349 if (vaddr & 0x7) { 350 writeSfsr(tc, false, ct, false, OtherFault, asi); 351 return new MemAddressNotAligned; 352 } 353 354 if (addr_mask) 355 vaddr = vaddr & VAddrAMask; 356 357 if (!validVirtualAddress(vaddr, addr_mask)) { 358 writeSfsr(tc, false, ct, false, VaOutOfRange, asi); 359 return new InstructionAccessException; 360 } 361 362 if (lsuIm) { 363 e = lookup(req->getVaddr(), part_id, true); 364 real = true; 365 context = 0; 366 } else { 367 e = lookup(vaddr, part_id, false, context); 368 } 369 370 if (e == NULL || !e->valid) { 371 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, 372 vaddr & ~BytesInPageMask | context); 373 if (real) 374 return new InstructionRealTranslationMiss; 375 else 376 return new FastInstructionAccessMMUMiss; 377 } 378 379 // were not priviledged accesing priv page 380 if (!priv && e->pte.priv()) { 381 writeSfsr(tc, false, ct, false, PrivViolation, asi); 382 return new InstructionAccessException; 383 } 384 385 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 386 req->getVaddr() & e->pte.size()); 387 return NoFault; 388} 389 390 391 392Fault 393DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 394{ 395 /* @todo this could really use some profiling and fixing to make it faster! */ 396 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 397 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 398 bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1; 399 uint64_t tl = tc->readMiscReg(MISCREG_TL); 400 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 401 bool hpriv = hpstate >> 2 & 0x1; 402 bool red = hpstate >> 5 >> 0x1; 403 bool addr_mask = pstate >> 3 & 0x1; 404 bool priv = pstate >> 2 & 0x1; 405 bool implicit = false; 406 bool real = false; 407 Addr vaddr = req->getVaddr(); 408 Addr size = req->getSize(); 409 ContextType ct; 410 int context; 411 ASI asi; 412 413 TlbEntry *e; 414 415 asi = (ASI)req->getAsi(); 416 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", 417 vaddr, size, asi); 418 419 if (asi == ASI_IMPLICIT) 420 implicit = true; 421 422 if (implicit) { 423 if (tl > 0) { 424 asi = ASI_N; 425 ct = Nucleus; 426 context = 0; 427 } else { 428 asi = ASI_P; 429 ct = Primary; 430 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 431 } 432 } else if (!hpriv && !red) { 433 if (tl > 0 || AsiIsNucleus(asi)) { 434 ct = Nucleus; 435 context = 0; 436 } else if (AsiIsSecondary(asi)) { 437 ct = Secondary; 438 context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT); 439 } else { 440 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 441 ct = Primary; //??? 442 } 443 444 // We need to check for priv level/asi priv 445 if (!priv && !AsiIsUnPriv(asi)) { 446 // It appears that context should be Nucleus in these cases? 447 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 448 return new PrivilegedAction; 449 } 450 if (priv && AsiIsHPriv(asi)) { 451 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 452 return new DataAccessException; 453 } 454 455 } 456 457 // If the asi is unaligned trap 458 if (vaddr & size-1) { 459 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); 460 return new MemAddressNotAligned; 461 } 462 463 if (addr_mask) 464 vaddr = vaddr & VAddrAMask; 465 466 if (!validVirtualAddress(vaddr, addr_mask)) { 467 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi); 468 return new DataAccessException; 469 } 470 471 if (!implicit) { 472 if (AsiIsLittle(asi)) 473 panic("Little Endian ASIs not supported\n"); 474 if (AsiIsBlock(asi)) 475 panic("Block ASIs not supported\n"); 476 if (AsiIsNoFault(asi)) 477 panic("No Fault ASIs not supported\n"); 478 if (AsiIsTwin(asi)) 479 panic("Twin ASIs not supported\n"); 480 if (AsiIsPartialStore(asi)) 481 panic("Partial Store ASIs not supported\n");
| 35#include "base/trace.hh" 36#include "cpu/thread_context.hh" 37#include "cpu/base.hh" 38#include "mem/packet_access.hh" 39#include "mem/request.hh" 40#include "sim/builder.hh" 41 42/* @todo remove some of the magic constants. -- ali 43 * */ 44namespace SparcISA 45{ 46 47TLB::TLB(const std::string &name, int s) 48 : SimObject(name), size(s) 49{ 50 // To make this work you'll have to change the hypervisor and OS 51 if (size > 64) 52 fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); 53 54 tlb = new TlbEntry[size]; 55 memset(tlb, 0, sizeof(TlbEntry) * size); 56} 57 58void 59TLB::clearUsedBits() 60{ 61 MapIter i; 62 for (i = lookupTable.begin(); i != lookupTable.end();) { 63 TlbEntry *t = i->second; 64 if (!t->pte.locked()) { 65 t->used = false; 66 usedEntries--; 67 } 68 } 69} 70 71 72void 73TLB::insert(Addr va, int partition_id, int context_id, bool real, 74 const PageTableEntry& PTE) 75{ 76 77 78 MapIter i; 79 TlbEntry *new_entry; 80 81 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x, pid=%d cid=%d r=%d\n", 82 va, partition_id, context_id, (int)real); 83 84 int x = -1; 85 for (x = 0; x < size; x++) { 86 if (!tlb[x].valid || !tlb[x].used) { 87 new_entry = &tlb[x]; 88 break; 89 } 90 } 91 92 // Update the last ently if their all locked 93 if (x == -1) 94 x = size - 1; 95 96 assert(PTE.valid()); 97 new_entry->range.va = va; 98 new_entry->range.size = PTE.size(); 99 new_entry->range.partitionId = partition_id; 100 new_entry->range.contextId = context_id; 101 new_entry->range.real = real; 102 new_entry->pte = PTE; 103 new_entry->used = true;; 104 new_entry->valid = true; 105 usedEntries++; 106 107 108 // Demap any entry that conflicts 109 i = lookupTable.find(new_entry->range); 110 if (i != lookupTable.end()) { 111 i->second->valid = false; 112 if (i->second->used) { 113 i->second->used = false; 114 usedEntries--; 115 } 116 DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n"); 117 lookupTable.erase(i); 118 } 119 120 lookupTable.insert(new_entry->range, new_entry);; 121 122 // If all entries have there used bit set, clear it on them all, but the 123 // one we just inserted 124 if (usedEntries == size) { 125 clearUsedBits(); 126 new_entry->used = true; 127 usedEntries++; 128 } 129 130} 131 132 133TlbEntry* 134TLB::lookup(Addr va, int partition_id, bool real, int context_id) 135{ 136 MapIter i; 137 TlbRange tr; 138 TlbEntry *t; 139 140 DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n", 141 va, partition_id, context_id, real); 142 // Assemble full address structure 143 tr.va = va; 144 tr.size = va + MachineBytes; 145 tr.contextId = context_id; 146 tr.partitionId = partition_id; 147 tr.real = real; 148 149 // Try to find the entry 150 i = lookupTable.find(tr); 151 if (i == lookupTable.end()) { 152 DPRINTF(TLB, "TLB: No valid entry found\n"); 153 return NULL; 154 } 155 DPRINTF(TLB, "TLB: Valid entry found\n"); 156 157 // Mark the entries used bit and clear other used bits in needed 158 t = i->second; 159 if (!t->used) { 160 t->used = true; 161 usedEntries++; 162 if (usedEntries == size) { 163 clearUsedBits(); 164 t->used = true; 165 usedEntries++; 166 } 167 } 168 169 return t; 170} 171 172 173void 174TLB::demapPage(Addr va, int partition_id, bool real, int context_id) 175{ 176 TlbRange tr; 177 MapIter i; 178 179 // Assemble full address structure 180 tr.va = va; 181 tr.size = va + MachineBytes; 182 tr.contextId = context_id; 183 tr.partitionId = partition_id; 184 tr.real = real; 185 186 // Demap any entry that conflicts 187 i = lookupTable.find(tr); 188 if (i != lookupTable.end()) { 189 i->second->valid = false; 190 if (i->second->used) { 191 i->second->used = false; 192 usedEntries--; 193 } 194 lookupTable.erase(i); 195 } 196} 197 198void 199TLB::demapContext(int partition_id, int context_id) 200{ 201 int x; 202 for (x = 0; x < size; x++) { 203 if (tlb[x].range.contextId == context_id && 204 tlb[x].range.partitionId == partition_id) { 205 tlb[x].valid = false; 206 if (tlb[x].used) { 207 tlb[x].used = false; 208 usedEntries--; 209 } 210 lookupTable.erase(tlb[x].range); 211 } 212 } 213} 214 215void 216TLB::demapAll(int partition_id) 217{ 218 int x; 219 for (x = 0; x < size; x++) { 220 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { 221 tlb[x].valid = false; 222 if (tlb[x].used) { 223 tlb[x].used = false; 224 usedEntries--; 225 } 226 lookupTable.erase(tlb[x].range); 227 } 228 } 229} 230 231void 232TLB::invalidateAll() 233{ 234 int x; 235 for (x = 0; x < size; x++) { 236 tlb[x].valid = false; 237 } 238 usedEntries = 0; 239} 240 241uint64_t 242TLB::TteRead(int entry) { 243 assert(entry < size); 244 return tlb[entry].pte(); 245} 246 247uint64_t 248TLB::TagRead(int entry) { 249 assert(entry < size); 250 uint64_t tag; 251 252 tag = tlb[entry].range.contextId | tlb[entry].range.va | 253 (uint64_t)tlb[entry].range.partitionId << 61; 254 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 255 tag |= (uint64_t)~tlb[entry].pte._size() << 56; 256 return tag; 257} 258 259bool 260TLB::validVirtualAddress(Addr va, bool am) 261{ 262 if (am) 263 return true; 264 if (va >= StartVAddrHole && va <= EndVAddrHole) 265 return false; 266 return true; 267} 268 269void 270TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, 271 bool se, FaultTypes ft, int asi) 272{ 273 uint64_t sfsr; 274 sfsr = tc->readMiscReg(reg); 275 276 if (sfsr & 0x1) 277 sfsr = 0x3; 278 else 279 sfsr = 1; 280 281 if (write) 282 sfsr |= 1 << 2; 283 sfsr |= ct << 4; 284 if (se) 285 sfsr |= 1 << 6; 286 sfsr |= ft << 7; 287 sfsr |= asi << 16; 288 tc->setMiscReg(reg, sfsr); 289} 290 291 292void 293ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct, 294 bool se, FaultTypes ft, int asi) 295{ 296 DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n", 297 (int)write, ct, ft, asi); 298 TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi); 299} 300 301void 302DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, 303 bool se, FaultTypes ft, int asi) 304{ 305 DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", 306 a, (int)write, ct, ft, asi); 307 TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); 308 tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a); 309} 310 311 312Fault 313ITB::translate(RequestPtr &req, ThreadContext *tc) 314{ 315 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 316 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 317 bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1; 318 uint64_t tl = tc->readMiscReg(MISCREG_TL); 319 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 320 bool addr_mask = pstate >> 3 & 0x1; 321 bool priv = pstate >> 2 & 0x1; 322 Addr vaddr = req->getVaddr(); 323 int context; 324 ContextType ct; 325 int asi; 326 bool real = false; 327 TlbEntry *e; 328 329 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n", 330 vaddr, req->getSize()); 331 332 assert(req->getAsi() == ASI_IMPLICIT); 333 334 if (tl > 0) { 335 asi = ASI_N; 336 ct = Nucleus; 337 context = 0; 338 } else { 339 asi = ASI_P; 340 ct = Primary; 341 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 342 } 343 344 if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) { 345 req->setPaddr(req->getVaddr() & PAddrImplMask); 346 return NoFault; 347 } 348 349 // If the asi is unaligned trap 350 if (vaddr & 0x7) { 351 writeSfsr(tc, false, ct, false, OtherFault, asi); 352 return new MemAddressNotAligned; 353 } 354 355 if (addr_mask) 356 vaddr = vaddr & VAddrAMask; 357 358 if (!validVirtualAddress(vaddr, addr_mask)) { 359 writeSfsr(tc, false, ct, false, VaOutOfRange, asi); 360 return new InstructionAccessException; 361 } 362 363 if (lsuIm) { 364 e = lookup(req->getVaddr(), part_id, true); 365 real = true; 366 context = 0; 367 } else { 368 e = lookup(vaddr, part_id, false, context); 369 } 370 371 if (e == NULL || !e->valid) { 372 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, 373 vaddr & ~BytesInPageMask | context); 374 if (real) 375 return new InstructionRealTranslationMiss; 376 else 377 return new FastInstructionAccessMMUMiss; 378 } 379 380 // were not priviledged accesing priv page 381 if (!priv && e->pte.priv()) { 382 writeSfsr(tc, false, ct, false, PrivViolation, asi); 383 return new InstructionAccessException; 384 } 385 386 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 387 req->getVaddr() & e->pte.size()); 388 return NoFault; 389} 390 391 392 393Fault 394DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 395{ 396 /* @todo this could really use some profiling and fixing to make it faster! */ 397 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 398 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 399 bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1; 400 uint64_t tl = tc->readMiscReg(MISCREG_TL); 401 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 402 bool hpriv = hpstate >> 2 & 0x1; 403 bool red = hpstate >> 5 >> 0x1; 404 bool addr_mask = pstate >> 3 & 0x1; 405 bool priv = pstate >> 2 & 0x1; 406 bool implicit = false; 407 bool real = false; 408 Addr vaddr = req->getVaddr(); 409 Addr size = req->getSize(); 410 ContextType ct; 411 int context; 412 ASI asi; 413 414 TlbEntry *e; 415 416 asi = (ASI)req->getAsi(); 417 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", 418 vaddr, size, asi); 419 420 if (asi == ASI_IMPLICIT) 421 implicit = true; 422 423 if (implicit) { 424 if (tl > 0) { 425 asi = ASI_N; 426 ct = Nucleus; 427 context = 0; 428 } else { 429 asi = ASI_P; 430 ct = Primary; 431 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 432 } 433 } else if (!hpriv && !red) { 434 if (tl > 0 || AsiIsNucleus(asi)) { 435 ct = Nucleus; 436 context = 0; 437 } else if (AsiIsSecondary(asi)) { 438 ct = Secondary; 439 context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT); 440 } else { 441 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 442 ct = Primary; //??? 443 } 444 445 // We need to check for priv level/asi priv 446 if (!priv && !AsiIsUnPriv(asi)) { 447 // It appears that context should be Nucleus in these cases? 448 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 449 return new PrivilegedAction; 450 } 451 if (priv && AsiIsHPriv(asi)) { 452 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 453 return new DataAccessException; 454 } 455 456 } 457 458 // If the asi is unaligned trap 459 if (vaddr & size-1) { 460 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); 461 return new MemAddressNotAligned; 462 } 463 464 if (addr_mask) 465 vaddr = vaddr & VAddrAMask; 466 467 if (!validVirtualAddress(vaddr, addr_mask)) { 468 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi); 469 return new DataAccessException; 470 } 471 472 if (!implicit) { 473 if (AsiIsLittle(asi)) 474 panic("Little Endian ASIs not supported\n"); 475 if (AsiIsBlock(asi)) 476 panic("Block ASIs not supported\n"); 477 if (AsiIsNoFault(asi)) 478 panic("No Fault ASIs not supported\n"); 479 if (AsiIsTwin(asi)) 480 panic("Twin ASIs not supported\n"); 481 if (AsiIsPartialStore(asi)) 482 panic("Partial Store ASIs not supported\n");
|
| 483 if (AsiIsInterrupt(asi)) 484 panic("Interrupt ASIs not supported\n");
|
482 483 if (AsiIsMmu(asi)) 484 goto handleMmuRegAccess; 485 if (AsiIsScratchPad(asi)) 486 goto handleScratchRegAccess;
| 485 486 if (AsiIsMmu(asi)) 487 goto handleMmuRegAccess; 488 if (AsiIsScratchPad(asi)) 489 goto handleScratchRegAccess;
|
| 490 if (AsiIsQueue(asi)) 491 goto handleQueueRegAccess;
|
487 488 if (!AsiIsReal(asi) && !AsiIsNucleus(asi)) 489 panic("Accessing ASI %#X. Should we?\n", asi); 490 } 491 492 if ((!lsuDm && !hpriv) || AsiIsReal(asi)) { 493 real = true; 494 context = 0; 495 }; 496 497 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) { 498 req->setPaddr(req->getVaddr() & PAddrImplMask); 499 return NoFault; 500 } 501 502 e = lookup(req->getVaddr(), part_id, real, context); 503 504 if (e == NULL || !e->valid) { 505 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, 506 vaddr & ~BytesInPageMask | context); 507 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n"); 508 if (real) 509 return new DataRealTranslationMiss; 510 else 511 return new FastDataAccessMMUMiss; 512 513 } 514 515 516 if (write && !e->pte.writable()) { 517 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); 518 return new FastDataAccessProtection; 519 } 520 521 if (e->pte.nofault() && !AsiIsNoFault(asi)) { 522 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); 523 return new DataAccessException; 524 } 525 526 if (e->pte.sideffect()) 527 req->setFlags(req->getFlags() | UNCACHEABLE); 528 529 530 if (!priv && e->pte.priv()) { 531 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 532 return new DataAccessException; 533 } 534 535 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 536 req->getVaddr() & e->pte.size()); 537 return NoFault; 538 /** Normal flow ends here. */ 539 540handleScratchRegAccess: 541 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 542 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 543 return new DataAccessException; 544 }
| 492 493 if (!AsiIsReal(asi) && !AsiIsNucleus(asi)) 494 panic("Accessing ASI %#X. Should we?\n", asi); 495 } 496 497 if ((!lsuDm && !hpriv) || AsiIsReal(asi)) { 498 real = true; 499 context = 0; 500 }; 501 502 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) { 503 req->setPaddr(req->getVaddr() & PAddrImplMask); 504 return NoFault; 505 } 506 507 e = lookup(req->getVaddr(), part_id, real, context); 508 509 if (e == NULL || !e->valid) { 510 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, 511 vaddr & ~BytesInPageMask | context); 512 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n"); 513 if (real) 514 return new DataRealTranslationMiss; 515 else 516 return new FastDataAccessMMUMiss; 517 518 } 519 520 521 if (write && !e->pte.writable()) { 522 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); 523 return new FastDataAccessProtection; 524 } 525 526 if (e->pte.nofault() && !AsiIsNoFault(asi)) { 527 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); 528 return new DataAccessException; 529 } 530 531 if (e->pte.sideffect()) 532 req->setFlags(req->getFlags() | UNCACHEABLE); 533 534 535 if (!priv && e->pte.priv()) { 536 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 537 return new DataAccessException; 538 } 539 540 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 541 req->getVaddr() & e->pte.size()); 542 return NoFault; 543 /** Normal flow ends here. */ 544 545handleScratchRegAccess: 546 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 547 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 548 return new DataAccessException; 549 }
|
| 550 goto regAccessOk; 551 552handleQueueRegAccess: 553 if (!priv && !hpriv) { 554 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 555 return new PrivilegedAction; 556 } 557 if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { 558 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 559 return new DataAccessException; 560 } 561 goto regAccessOk; 562 563regAccessOk:
|
545handleMmuRegAccess: 546 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n"); 547 req->setMmapedIpr(true); 548 req->setPaddr(req->getVaddr()); 549 return NoFault; 550}; 551 552Tick 553DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) 554{ 555 Addr va = pkt->getAddr(); 556 ASI asi = (ASI)pkt->req->getAsi(); 557 558 DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", 559 (uint32_t)pkt->req->getAsi(), pkt->getAddr()); 560 561 switch (asi) { 562 case ASI_LSU_CONTROL_REG: 563 assert(va == 0); 564 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL)); 565 break; 566 case ASI_MMU: 567 switch (va) { 568 case 0x8: 569 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT)); 570 break; 571 case 0x10: 572 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT)); 573 break; 574 default: 575 goto doMmuReadError; 576 } 577 break;
| 564handleMmuRegAccess: 565 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n"); 566 req->setMmapedIpr(true); 567 req->setPaddr(req->getVaddr()); 568 return NoFault; 569}; 570 571Tick 572DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) 573{ 574 Addr va = pkt->getAddr(); 575 ASI asi = (ASI)pkt->req->getAsi(); 576 577 DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", 578 (uint32_t)pkt->req->getAsi(), pkt->getAddr()); 579 580 switch (asi) { 581 case ASI_LSU_CONTROL_REG: 582 assert(va == 0); 583 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL)); 584 break; 585 case ASI_MMU: 586 switch (va) { 587 case 0x8: 588 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT)); 589 break; 590 case 0x10: 591 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT)); 592 break; 593 default: 594 goto doMmuReadError; 595 } 596 break;
|
| 597 case ASI_QUEUE: 598 pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 599 (va >> 4) - 0x3c)); 600 break;
|
578 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 579 assert(va == 0); 580 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); 581 break; 582 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 583 assert(va == 0); 584 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); 585 break; 586 case ASI_DMMU_CTXT_ZERO_CONFIG: 587 assert(va == 0); 588 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG)); 589 break; 590 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 591 assert(va == 0); 592 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); 593 break; 594 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 595 assert(va == 0); 596 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); 597 break; 598 case ASI_IMMU_CTXT_ZERO_CONFIG: 599 assert(va == 0); 600 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG)); 601 break; 602 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 603 assert(va == 0); 604 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); 605 break; 606 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 607 assert(va == 0); 608 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); 609 break; 610 case ASI_DMMU_CTXT_NONZERO_CONFIG: 611 assert(va == 0); 612 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); 613 break; 614 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 615 assert(va == 0); 616 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); 617 break; 618 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 619 assert(va == 0); 620 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); 621 break; 622 case ASI_IMMU_CTXT_NONZERO_CONFIG: 623 assert(va == 0); 624 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); 625 break; 626 case ASI_HYP_SCRATCHPAD: 627 case ASI_SCRATCHPAD: 628 pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3))); 629 break; 630 case ASI_DMMU: 631 switch (va) { 632 case 0x80: 633 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID)); 634 break; 635 default: 636 goto doMmuReadError; 637 } 638 break; 639 default: 640doMmuReadError: 641 panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", 642 (uint32_t)asi, va); 643 } 644 pkt->result = Packet::Success; 645 return tc->getCpuPtr()->cycles(1); 646} 647 648Tick 649DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) 650{ 651 uint64_t data = gtoh(pkt->get<uint64_t>()); 652 Addr va = pkt->getAddr(); 653 ASI asi = (ASI)pkt->req->getAsi(); 654 655 DPRINTF(IPR, "Memory Mapped IPR Write: asi=#%X a=%#x d=%#X\n", 656 (uint32_t)asi, va, data); 657 658 switch (asi) { 659 case ASI_LSU_CONTROL_REG: 660 assert(va == 0); 661 tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data); 662 break; 663 case ASI_MMU: 664 switch (va) { 665 case 0x8: 666 tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data); 667 break; 668 case 0x10: 669 tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data); 670 break; 671 default: 672 goto doMmuWriteError; 673 } 674 break;
| 601 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 602 assert(va == 0); 603 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); 604 break; 605 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 606 assert(va == 0); 607 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); 608 break; 609 case ASI_DMMU_CTXT_ZERO_CONFIG: 610 assert(va == 0); 611 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG)); 612 break; 613 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 614 assert(va == 0); 615 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); 616 break; 617 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 618 assert(va == 0); 619 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); 620 break; 621 case ASI_IMMU_CTXT_ZERO_CONFIG: 622 assert(va == 0); 623 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG)); 624 break; 625 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 626 assert(va == 0); 627 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); 628 break; 629 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 630 assert(va == 0); 631 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); 632 break; 633 case ASI_DMMU_CTXT_NONZERO_CONFIG: 634 assert(va == 0); 635 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); 636 break; 637 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 638 assert(va == 0); 639 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); 640 break; 641 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 642 assert(va == 0); 643 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); 644 break; 645 case ASI_IMMU_CTXT_NONZERO_CONFIG: 646 assert(va == 0); 647 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); 648 break; 649 case ASI_HYP_SCRATCHPAD: 650 case ASI_SCRATCHPAD: 651 pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3))); 652 break; 653 case ASI_DMMU: 654 switch (va) { 655 case 0x80: 656 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID)); 657 break; 658 default: 659 goto doMmuReadError; 660 } 661 break; 662 default: 663doMmuReadError: 664 panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", 665 (uint32_t)asi, va); 666 } 667 pkt->result = Packet::Success; 668 return tc->getCpuPtr()->cycles(1); 669} 670 671Tick 672DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) 673{ 674 uint64_t data = gtoh(pkt->get<uint64_t>()); 675 Addr va = pkt->getAddr(); 676 ASI asi = (ASI)pkt->req->getAsi(); 677 678 DPRINTF(IPR, "Memory Mapped IPR Write: asi=#%X a=%#x d=%#X\n", 679 (uint32_t)asi, va, data); 680 681 switch (asi) { 682 case ASI_LSU_CONTROL_REG: 683 assert(va == 0); 684 tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data); 685 break; 686 case ASI_MMU: 687 switch (va) { 688 case 0x8: 689 tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data); 690 break; 691 case 0x10: 692 tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data); 693 break; 694 default: 695 goto doMmuWriteError; 696 } 697 break;
|
| 698 case ASI_QUEUE: 699 assert(mbits(va,13,6) == va); 700 tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 701 (va >> 4) - 0x3c, data); 702 break;
|
675 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 676 assert(va == 0); 677 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data); 678 break; 679 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 680 assert(va == 0); 681 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data); 682 break; 683 case ASI_DMMU_CTXT_ZERO_CONFIG: 684 assert(va == 0); 685 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data); 686 break; 687 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 688 assert(va == 0); 689 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data); 690 break; 691 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 692 assert(va == 0); 693 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data); 694 break; 695 case ASI_IMMU_CTXT_ZERO_CONFIG: 696 assert(va == 0); 697 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data); 698 break; 699 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 700 assert(va == 0); 701 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data); 702 break; 703 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 704 assert(va == 0); 705 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data); 706 break; 707 case ASI_DMMU_CTXT_NONZERO_CONFIG: 708 assert(va == 0); 709 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data); 710 break; 711 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 712 assert(va == 0); 713 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data); 714 break; 715 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 716 assert(va == 0); 717 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data); 718 break; 719 case ASI_IMMU_CTXT_NONZERO_CONFIG: 720 assert(va == 0); 721 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data); 722 break; 723 case ASI_HYP_SCRATCHPAD: 724 case ASI_SCRATCHPAD: 725 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); 726 break; 727 case ASI_DMMU: 728 switch (va) { 729 case 0x80: 730 tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data); 731 break; 732 default: 733 goto doMmuWriteError; 734 } 735 break; 736 default: 737doMmuWriteError: 738 panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", 739 (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); 740 } 741 pkt->result = Packet::Success; 742 return tc->getCpuPtr()->cycles(1); 743} 744 745void 746TLB::serialize(std::ostream &os) 747{ 748 panic("Need to implement serialize tlb for SPARC\n"); 749} 750 751void 752TLB::unserialize(Checkpoint *cp, const std::string §ion) 753{ 754 panic("Need to implement unserialize tlb for SPARC\n"); 755} 756 757 758DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) 759 760BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) 761 762 Param<int> size; 763 764END_DECLARE_SIM_OBJECT_PARAMS(ITB) 765 766BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) 767 768 INIT_PARAM_DFLT(size, "TLB size", 48) 769 770END_INIT_SIM_OBJECT_PARAMS(ITB) 771 772 773CREATE_SIM_OBJECT(ITB) 774{ 775 return new ITB(getInstanceName(), size); 776} 777 778REGISTER_SIM_OBJECT("SparcITB", ITB) 779 780BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) 781 782 Param<int> size; 783 784END_DECLARE_SIM_OBJECT_PARAMS(DTB) 785 786BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) 787 788 INIT_PARAM_DFLT(size, "TLB size", 64) 789 790END_INIT_SIM_OBJECT_PARAMS(DTB) 791 792 793CREATE_SIM_OBJECT(DTB) 794{ 795 return new DTB(getInstanceName(), size); 796} 797 798REGISTER_SIM_OBJECT("SparcDTB", DTB) 799}
| 703 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 704 assert(va == 0); 705 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data); 706 break; 707 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 708 assert(va == 0); 709 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data); 710 break; 711 case ASI_DMMU_CTXT_ZERO_CONFIG: 712 assert(va == 0); 713 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data); 714 break; 715 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 716 assert(va == 0); 717 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data); 718 break; 719 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 720 assert(va == 0); 721 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data); 722 break; 723 case ASI_IMMU_CTXT_ZERO_CONFIG: 724 assert(va == 0); 725 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data); 726 break; 727 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 728 assert(va == 0); 729 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data); 730 break; 731 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 732 assert(va == 0); 733 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data); 734 break; 735 case ASI_DMMU_CTXT_NONZERO_CONFIG: 736 assert(va == 0); 737 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data); 738 break; 739 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 740 assert(va == 0); 741 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data); 742 break; 743 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 744 assert(va == 0); 745 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data); 746 break; 747 case ASI_IMMU_CTXT_NONZERO_CONFIG: 748 assert(va == 0); 749 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data); 750 break; 751 case ASI_HYP_SCRATCHPAD: 752 case ASI_SCRATCHPAD: 753 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); 754 break; 755 case ASI_DMMU: 756 switch (va) { 757 case 0x80: 758 tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data); 759 break; 760 default: 761 goto doMmuWriteError; 762 } 763 break; 764 default: 765doMmuWriteError: 766 panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", 767 (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); 768 } 769 pkt->result = Packet::Success; 770 return tc->getCpuPtr()->cycles(1); 771} 772 773void 774TLB::serialize(std::ostream &os) 775{ 776 panic("Need to implement serialize tlb for SPARC\n"); 777} 778 779void 780TLB::unserialize(Checkpoint *cp, const std::string §ion) 781{ 782 panic("Need to implement unserialize tlb for SPARC\n"); 783} 784 785 786DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) 787 788BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) 789 790 Param<int> size; 791 792END_DECLARE_SIM_OBJECT_PARAMS(ITB) 793 794BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) 795 796 INIT_PARAM_DFLT(size, "TLB size", 48) 797 798END_INIT_SIM_OBJECT_PARAMS(ITB) 799 800 801CREATE_SIM_OBJECT(ITB) 802{ 803 return new ITB(getInstanceName(), size); 804} 805 806REGISTER_SIM_OBJECT("SparcITB", ITB) 807 808BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) 809 810 Param<int> size; 811 812END_DECLARE_SIM_OBJECT_PARAMS(DTB) 813 814BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) 815 816 INIT_PARAM_DFLT(size, "TLB size", 64) 817 818END_INIT_SIM_OBJECT_PARAMS(DTB) 819 820 821CREATE_SIM_OBJECT(DTB) 822{ 823 return new DTB(getInstanceName(), size); 824} 825 826REGISTER_SIM_OBJECT("SparcDTB", DTB) 827}
|