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"
| 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/tlb.hh" 33#include "sim/builder.hh"
| |
34#include "arch/sparc/miscregfile.hh"
| 32#include "arch/sparc/miscregfile.hh"
|
| 33#include "arch/sparc/tlb.hh" 34#include "base/trace.hh"
|
35#include "cpu/thread_context.hh"
| 35#include "cpu/thread_context.hh"
|
| 36#include "sim/builder.hh"
|
36 37/* @todo remove some of the magic constants. -- ali 38 * */ 39namespace SparcISA 40{ 41 42TLB::TLB(const std::string &name, int s) 43 : SimObject(name), size(s) 44{ 45 // To make this work you'll have to change the hypervisor and OS 46 if (size > 64) 47 fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); 48 49 tlb = new TlbEntry[size]; 50 memset(tlb, 0, sizeof(TlbEntry) * size); 51} 52 53void 54TLB::clearUsedBits() 55{ 56 MapIter i; 57 for (i = lookupTable.begin(); i != lookupTable.end();) { 58 TlbEntry *t = i->second; 59 if (!t->pte.locked()) { 60 t->used = false; 61 usedEntries--; 62 } 63 } 64} 65 66 67void 68TLB::insert(Addr va, int partition_id, int context_id, bool real, 69 const PageTableEntry& PTE) 70{ 71 72 73 MapIter i; 74 TlbEntry *new_entry;
| 37 38/* @todo remove some of the magic constants. -- ali 39 * */ 40namespace SparcISA 41{ 42 43TLB::TLB(const std::string &name, int s) 44 : SimObject(name), size(s) 45{ 46 // To make this work you'll have to change the hypervisor and OS 47 if (size > 64) 48 fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); 49 50 tlb = new TlbEntry[size]; 51 memset(tlb, 0, sizeof(TlbEntry) * size); 52} 53 54void 55TLB::clearUsedBits() 56{ 57 MapIter i; 58 for (i = lookupTable.begin(); i != lookupTable.end();) { 59 TlbEntry *t = i->second; 60 if (!t->pte.locked()) { 61 t->used = false; 62 usedEntries--; 63 } 64 } 65} 66 67 68void 69TLB::insert(Addr va, int partition_id, int context_id, bool real, 70 const PageTableEntry& PTE) 71{ 72 73 74 MapIter i; 75 TlbEntry *new_entry;
|
| 76 77 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x, pid=%d cid=%d r=%d\n", 78 va, partition_id, context_id, (int)real); 79
|
75 int x = -1; 76 for (x = 0; x < size; x++) { 77 if (!tlb[x].valid || !tlb[x].used) { 78 new_entry = &tlb[x]; 79 break; 80 } 81 } 82 83 // Update the last ently if their all locked 84 if (x == -1) 85 x = size - 1; 86 87 assert(PTE.valid()); 88 new_entry->range.va = va; 89 new_entry->range.size = PTE.size(); 90 new_entry->range.partitionId = partition_id; 91 new_entry->range.contextId = context_id; 92 new_entry->range.real = real; 93 new_entry->pte = PTE; 94 new_entry->used = true;; 95 new_entry->valid = true; 96 usedEntries++; 97 98 99 // Demap any entry that conflicts 100 i = lookupTable.find(new_entry->range); 101 if (i != lookupTable.end()) { 102 i->second->valid = false; 103 if (i->second->used) { 104 i->second->used = false; 105 usedEntries--; 106 }
| 80 int x = -1; 81 for (x = 0; x < size; x++) { 82 if (!tlb[x].valid || !tlb[x].used) { 83 new_entry = &tlb[x]; 84 break; 85 } 86 } 87 88 // Update the last ently if their all locked 89 if (x == -1) 90 x = size - 1; 91 92 assert(PTE.valid()); 93 new_entry->range.va = va; 94 new_entry->range.size = PTE.size(); 95 new_entry->range.partitionId = partition_id; 96 new_entry->range.contextId = context_id; 97 new_entry->range.real = real; 98 new_entry->pte = PTE; 99 new_entry->used = true;; 100 new_entry->valid = true; 101 usedEntries++; 102 103 104 // Demap any entry that conflicts 105 i = lookupTable.find(new_entry->range); 106 if (i != lookupTable.end()) { 107 i->second->valid = false; 108 if (i->second->used) { 109 i->second->used = false; 110 usedEntries--; 111 }
|
| 112 DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n");
|
107 lookupTable.erase(i); 108 } 109 110 lookupTable.insert(new_entry->range, new_entry);; 111 112 // If all entries have there used bit set, clear it on them all, but the 113 // one we just inserted 114 if (usedEntries == size) { 115 clearUsedBits(); 116 new_entry->used = true; 117 usedEntries++; 118 } 119 120} 121 122 123TlbEntry* 124TLB::lookup(Addr va, int partition_id, bool real, int context_id) 125{ 126 MapIter i; 127 TlbRange tr; 128 TlbEntry *t; 129
| 113 lookupTable.erase(i); 114 } 115 116 lookupTable.insert(new_entry->range, new_entry);; 117 118 // If all entries have there used bit set, clear it on them all, but the 119 // one we just inserted 120 if (usedEntries == size) { 121 clearUsedBits(); 122 new_entry->used = true; 123 usedEntries++; 124 } 125 126} 127 128 129TlbEntry* 130TLB::lookup(Addr va, int partition_id, bool real, int context_id) 131{ 132 MapIter i; 133 TlbRange tr; 134 TlbEntry *t; 135
|
| 136 DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n", 137 va, partition_id, context_id, real);
|
130 // Assemble full address structure 131 tr.va = va; 132 tr.size = va + MachineBytes; 133 tr.contextId = context_id; 134 tr.partitionId = partition_id; 135 tr.real = real; 136 137 // Try to find the entry 138 i = lookupTable.find(tr); 139 if (i == lookupTable.end()) {
| 138 // Assemble full address structure 139 tr.va = va; 140 tr.size = va + MachineBytes; 141 tr.contextId = context_id; 142 tr.partitionId = partition_id; 143 tr.real = real; 144 145 // Try to find the entry 146 i = lookupTable.find(tr); 147 if (i == lookupTable.end()) {
|
| 148 DPRINTF(TLB, "TLB: No valid entry found\n");
|
140 return NULL; 141 }
| 149 return NULL; 150 }
|
| 151 DPRINTF(TLB, "TLB: Valid entry found\n");
|
142 143 // Mark the entries used bit and clear other used bits in needed 144 t = i->second; 145 if (!t->used) { 146 t->used = true; 147 usedEntries++; 148 if (usedEntries == size) { 149 clearUsedBits(); 150 t->used = true; 151 usedEntries++; 152 } 153 } 154 155 return t; 156} 157 158 159void 160TLB::demapPage(Addr va, int partition_id, bool real, int context_id) 161{ 162 TlbRange tr; 163 MapIter i; 164 165 // Assemble full address structure 166 tr.va = va; 167 tr.size = va + MachineBytes; 168 tr.contextId = context_id; 169 tr.partitionId = partition_id; 170 tr.real = real; 171 172 // Demap any entry that conflicts 173 i = lookupTable.find(tr); 174 if (i != lookupTable.end()) { 175 i->second->valid = false; 176 if (i->second->used) { 177 i->second->used = false; 178 usedEntries--; 179 } 180 lookupTable.erase(i); 181 } 182} 183 184void 185TLB::demapContext(int partition_id, int context_id) 186{ 187 int x; 188 for (x = 0; x < size; x++) { 189 if (tlb[x].range.contextId == context_id && 190 tlb[x].range.partitionId == partition_id) { 191 tlb[x].valid = false; 192 if (tlb[x].used) { 193 tlb[x].used = false; 194 usedEntries--; 195 } 196 lookupTable.erase(tlb[x].range); 197 } 198 } 199} 200 201void 202TLB::demapAll(int partition_id) 203{ 204 int x; 205 for (x = 0; x < size; x++) { 206 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { 207 tlb[x].valid = false; 208 if (tlb[x].used) { 209 tlb[x].used = false; 210 usedEntries--; 211 } 212 lookupTable.erase(tlb[x].range); 213 } 214 } 215} 216 217void 218TLB::invalidateAll() 219{ 220 int x; 221 for (x = 0; x < size; x++) { 222 tlb[x].valid = false; 223 } 224 usedEntries = 0; 225} 226 227uint64_t 228TLB::TteRead(int entry) { 229 assert(entry < size); 230 return tlb[entry].pte(); 231} 232 233uint64_t 234TLB::TagRead(int entry) { 235 assert(entry < size); 236 uint64_t tag; 237 238 tag = tlb[entry].range.contextId | tlb[entry].range.va | 239 (uint64_t)tlb[entry].range.partitionId << 61; 240 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 241 tag |= (uint64_t)~tlb[entry].pte._size() << 56; 242 return tag; 243} 244 245bool 246TLB::validVirtualAddress(Addr va, bool am) 247{ 248 if (am) 249 return true; 250 if (va >= StartVAddrHole && va <= EndVAddrHole) 251 return false; 252 return true; 253} 254 255void 256TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, 257 bool se, FaultTypes ft, int asi) 258{ 259 uint64_t sfsr; 260 sfsr = tc->readMiscReg(reg); 261 262 if (sfsr & 0x1) 263 sfsr = 0x3; 264 else 265 sfsr = 1; 266 267 if (write) 268 sfsr |= 1 << 2; 269 sfsr |= ct << 4; 270 if (se) 271 sfsr |= 1 << 6; 272 sfsr |= ft << 7; 273 sfsr |= asi << 16; 274 tc->setMiscReg(reg, sfsr); 275} 276 277 278void 279ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct, 280 bool se, FaultTypes ft, int asi) 281{
| 152 153 // Mark the entries used bit and clear other used bits in needed 154 t = i->second; 155 if (!t->used) { 156 t->used = true; 157 usedEntries++; 158 if (usedEntries == size) { 159 clearUsedBits(); 160 t->used = true; 161 usedEntries++; 162 } 163 } 164 165 return t; 166} 167 168 169void 170TLB::demapPage(Addr va, int partition_id, bool real, int context_id) 171{ 172 TlbRange tr; 173 MapIter i; 174 175 // Assemble full address structure 176 tr.va = va; 177 tr.size = va + MachineBytes; 178 tr.contextId = context_id; 179 tr.partitionId = partition_id; 180 tr.real = real; 181 182 // Demap any entry that conflicts 183 i = lookupTable.find(tr); 184 if (i != lookupTable.end()) { 185 i->second->valid = false; 186 if (i->second->used) { 187 i->second->used = false; 188 usedEntries--; 189 } 190 lookupTable.erase(i); 191 } 192} 193 194void 195TLB::demapContext(int partition_id, int context_id) 196{ 197 int x; 198 for (x = 0; x < size; x++) { 199 if (tlb[x].range.contextId == context_id && 200 tlb[x].range.partitionId == partition_id) { 201 tlb[x].valid = false; 202 if (tlb[x].used) { 203 tlb[x].used = false; 204 usedEntries--; 205 } 206 lookupTable.erase(tlb[x].range); 207 } 208 } 209} 210 211void 212TLB::demapAll(int partition_id) 213{ 214 int x; 215 for (x = 0; x < size; x++) { 216 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { 217 tlb[x].valid = false; 218 if (tlb[x].used) { 219 tlb[x].used = false; 220 usedEntries--; 221 } 222 lookupTable.erase(tlb[x].range); 223 } 224 } 225} 226 227void 228TLB::invalidateAll() 229{ 230 int x; 231 for (x = 0; x < size; x++) { 232 tlb[x].valid = false; 233 } 234 usedEntries = 0; 235} 236 237uint64_t 238TLB::TteRead(int entry) { 239 assert(entry < size); 240 return tlb[entry].pte(); 241} 242 243uint64_t 244TLB::TagRead(int entry) { 245 assert(entry < size); 246 uint64_t tag; 247 248 tag = tlb[entry].range.contextId | tlb[entry].range.va | 249 (uint64_t)tlb[entry].range.partitionId << 61; 250 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 251 tag |= (uint64_t)~tlb[entry].pte._size() << 56; 252 return tag; 253} 254 255bool 256TLB::validVirtualAddress(Addr va, bool am) 257{ 258 if (am) 259 return true; 260 if (va >= StartVAddrHole && va <= EndVAddrHole) 261 return false; 262 return true; 263} 264 265void 266TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, 267 bool se, FaultTypes ft, int asi) 268{ 269 uint64_t sfsr; 270 sfsr = tc->readMiscReg(reg); 271 272 if (sfsr & 0x1) 273 sfsr = 0x3; 274 else 275 sfsr = 1; 276 277 if (write) 278 sfsr |= 1 << 2; 279 sfsr |= ct << 4; 280 if (se) 281 sfsr |= 1 << 6; 282 sfsr |= ft << 7; 283 sfsr |= asi << 16; 284 tc->setMiscReg(reg, sfsr); 285} 286 287 288void 289ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct, 290 bool se, FaultTypes ft, int asi) 291{
|
| 292 DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n", 293 (int)write, ct, ft, asi);
|
282 TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi); 283} 284 285void 286DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, 287 bool se, FaultTypes ft, int asi) 288{
| 294 TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi); 295} 296 297void 298DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, 299 bool se, FaultTypes ft, int asi) 300{
|
| 301 DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", 302 a, (int)write, ct, ft, asi);
|
289 TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); 290 tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a); 291} 292 293 294Fault 295ITB::translate(RequestPtr &req, ThreadContext *tc) 296{ 297 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 298 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 299 bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1; 300 uint64_t tl = tc->readMiscReg(MISCREG_TL); 301 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 302 bool addr_mask = pstate >> 3 & 0x1; 303 bool priv = pstate >> 2 & 0x1; 304 Addr vaddr = req->getVaddr(); 305 int context; 306 ContextType ct; 307 int asi; 308 bool real = false; 309 TlbEntry *e; 310
| 303 TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); 304 tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a); 305} 306 307 308Fault 309ITB::translate(RequestPtr &req, ThreadContext *tc) 310{ 311 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 312 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 313 bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1; 314 uint64_t tl = tc->readMiscReg(MISCREG_TL); 315 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 316 bool addr_mask = pstate >> 3 & 0x1; 317 bool priv = pstate >> 2 & 0x1; 318 Addr vaddr = req->getVaddr(); 319 int context; 320 ContextType ct; 321 int asi; 322 bool real = false; 323 TlbEntry *e; 324
|
| 325 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n", 326 vaddr, req->getSize()); 327
|
311 assert(req->getAsi() == ASI_IMPLICIT); 312 313 if (tl > 0) { 314 asi = ASI_N; 315 ct = Nucleus; 316 context = 0; 317 } else { 318 asi = ASI_P; 319 ct = Primary; 320 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 321 } 322 323 if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) { 324 req->setPaddr(req->getVaddr() & PAddrImplMask); 325 return NoFault; 326 } 327 328 // If the asi is unaligned trap 329 if (vaddr & 0x7) { 330 writeSfsr(tc, false, ct, false, OtherFault, asi); 331 return new MemAddressNotAligned; 332 } 333 334 if (addr_mask) 335 vaddr = vaddr & VAddrAMask; 336 337 if (!validVirtualAddress(vaddr, addr_mask)) { 338 writeSfsr(tc, false, ct, false, VaOutOfRange, asi); 339 return new InstructionAccessException; 340 } 341 342 if (lsuIm) { 343 e = lookup(req->getVaddr(), part_id, true); 344 real = true; 345 context = 0; 346 } else { 347 e = lookup(vaddr, part_id, false, context); 348 } 349 350 if (e == NULL || !e->valid) { 351 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, 352 vaddr & ~BytesInPageMask | context); 353 if (real) 354 return new InstructionRealTranslationMiss; 355 else 356 return new FastInstructionAccessMMUMiss; 357 } 358 359 // were not priviledged accesing priv page 360 if (!priv && e->pte.priv()) { 361 writeSfsr(tc, false, ct, false, PrivViolation, asi); 362 return new InstructionAccessException; 363 } 364 365 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 366 req->getVaddr() & e->pte.size()); 367 return NoFault; 368} 369 370 371 372Fault 373DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 374{ 375 /* @todo this could really use some profiling and fixing to make it faster! */ 376 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 377 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 378 bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1; 379 uint64_t tl = tc->readMiscReg(MISCREG_TL); 380 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 381 bool hpriv = hpstate >> 2 & 0x1; 382 bool red = hpstate >> 5 >> 0x1; 383 bool addr_mask = pstate >> 3 & 0x1; 384 bool priv = pstate >> 2 & 0x1; 385 bool implicit = false; 386 bool real = false; 387 Addr vaddr = req->getVaddr();
| 328 assert(req->getAsi() == ASI_IMPLICIT); 329 330 if (tl > 0) { 331 asi = ASI_N; 332 ct = Nucleus; 333 context = 0; 334 } else { 335 asi = ASI_P; 336 ct = Primary; 337 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 338 } 339 340 if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) { 341 req->setPaddr(req->getVaddr() & PAddrImplMask); 342 return NoFault; 343 } 344 345 // If the asi is unaligned trap 346 if (vaddr & 0x7) { 347 writeSfsr(tc, false, ct, false, OtherFault, asi); 348 return new MemAddressNotAligned; 349 } 350 351 if (addr_mask) 352 vaddr = vaddr & VAddrAMask; 353 354 if (!validVirtualAddress(vaddr, addr_mask)) { 355 writeSfsr(tc, false, ct, false, VaOutOfRange, asi); 356 return new InstructionAccessException; 357 } 358 359 if (lsuIm) { 360 e = lookup(req->getVaddr(), part_id, true); 361 real = true; 362 context = 0; 363 } else { 364 e = lookup(vaddr, part_id, false, context); 365 } 366 367 if (e == NULL || !e->valid) { 368 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, 369 vaddr & ~BytesInPageMask | context); 370 if (real) 371 return new InstructionRealTranslationMiss; 372 else 373 return new FastInstructionAccessMMUMiss; 374 } 375 376 // were not priviledged accesing priv page 377 if (!priv && e->pte.priv()) { 378 writeSfsr(tc, false, ct, false, PrivViolation, asi); 379 return new InstructionAccessException; 380 } 381 382 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 383 req->getVaddr() & e->pte.size()); 384 return NoFault; 385} 386 387 388 389Fault 390DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 391{ 392 /* @todo this could really use some profiling and fixing to make it faster! */ 393 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 394 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 395 bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1; 396 uint64_t tl = tc->readMiscReg(MISCREG_TL); 397 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 398 bool hpriv = hpstate >> 2 & 0x1; 399 bool red = hpstate >> 5 >> 0x1; 400 bool addr_mask = pstate >> 3 & 0x1; 401 bool priv = pstate >> 2 & 0x1; 402 bool implicit = false; 403 bool real = false; 404 Addr vaddr = req->getVaddr();
|
| 405 Addr size = req->getSize();
|
388 ContextType ct; 389 int context; 390 ASI asi; 391 392 TlbEntry *e; 393
| 406 ContextType ct; 407 int context; 408 ASI asi; 409 410 TlbEntry *e; 411
|
394
| |
395 asi = (ASI)req->getAsi();
| 412 asi = (ASI)req->getAsi();
|
| 413 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", 414 vaddr, size, asi); 415
|
396 if (asi == ASI_IMPLICIT) 397 implicit = true; 398 399 if (implicit) { 400 if (tl > 0) { 401 asi = ASI_N; 402 ct = Nucleus; 403 context = 0; 404 } else { 405 asi = ASI_P; 406 ct = Primary; 407 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 408 } 409 } else if (!hpriv && !red) { 410 if (tl > 0) { 411 ct = Nucleus; 412 context = 0; 413 } else if (AsiIsSecondary(asi)) { 414 ct = Secondary; 415 context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT); 416 } else { 417 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 418 ct = Primary; //??? 419 } 420 421 // We need to check for priv level/asi priv 422 if (!priv && !AsiIsUnPriv(asi)) { 423 // It appears that context should be Nucleus in these cases? 424 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 425 return new PrivilegedAction; 426 } 427 if (priv && AsiIsHPriv(asi)) { 428 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 429 return new DataAccessException; 430 } 431 432 } 433 434 // If the asi is unaligned trap
| 416 if (asi == ASI_IMPLICIT) 417 implicit = true; 418 419 if (implicit) { 420 if (tl > 0) { 421 asi = ASI_N; 422 ct = Nucleus; 423 context = 0; 424 } else { 425 asi = ASI_P; 426 ct = Primary; 427 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 428 } 429 } else if (!hpriv && !red) { 430 if (tl > 0) { 431 ct = Nucleus; 432 context = 0; 433 } else if (AsiIsSecondary(asi)) { 434 ct = Secondary; 435 context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT); 436 } else { 437 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 438 ct = Primary; //??? 439 } 440 441 // We need to check for priv level/asi priv 442 if (!priv && !AsiIsUnPriv(asi)) { 443 // It appears that context should be Nucleus in these cases? 444 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 445 return new PrivilegedAction; 446 } 447 if (priv && AsiIsHPriv(asi)) { 448 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 449 return new DataAccessException; 450 } 451 452 } 453 454 // If the asi is unaligned trap
|
435 if (AsiIsBlock(asi) && vaddr & 0x3f || vaddr & 0x7) {
| 455 if (vaddr & size-1) {
|
436 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); 437 return new MemAddressNotAligned; 438 } 439 440 if (addr_mask) 441 vaddr = vaddr & VAddrAMask; 442 443 if (!validVirtualAddress(vaddr, addr_mask)) { 444 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi); 445 return new DataAccessException; 446 } 447 448 if (!implicit) { 449 if (AsiIsLittle(asi)) 450 panic("Little Endian ASIs not supported\n"); 451 if (AsiIsBlock(asi)) 452 panic("Block ASIs not supported\n"); 453 if (AsiIsNoFault(asi)) 454 panic("No Fault ASIs not supported\n"); 455 if (AsiIsTwin(asi)) 456 panic("Twin ASIs not supported\n"); 457 if (AsiIsPartialStore(asi)) 458 panic("Partial Store ASIs not supported\n"); 459 if (AsiIsMmu(asi)) 460 goto handleMmuRegAccess; 461 462 if (AsiIsScratchPad(asi)) 463 goto handleScratchRegAccess; 464 } 465 466 if ((!lsuDm && !hpriv) || AsiIsReal(asi)) { 467 real = true; 468 context = 0; 469 }; 470 471 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) { 472 req->setPaddr(req->getVaddr() & PAddrImplMask); 473 return NoFault; 474 } 475 476 e = lookup(req->getVaddr(), part_id, real, context); 477 478 if (e == NULL || !e->valid) { 479 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, 480 vaddr & ~BytesInPageMask | context);
| 456 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); 457 return new MemAddressNotAligned; 458 } 459 460 if (addr_mask) 461 vaddr = vaddr & VAddrAMask; 462 463 if (!validVirtualAddress(vaddr, addr_mask)) { 464 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi); 465 return new DataAccessException; 466 } 467 468 if (!implicit) { 469 if (AsiIsLittle(asi)) 470 panic("Little Endian ASIs not supported\n"); 471 if (AsiIsBlock(asi)) 472 panic("Block ASIs not supported\n"); 473 if (AsiIsNoFault(asi)) 474 panic("No Fault ASIs not supported\n"); 475 if (AsiIsTwin(asi)) 476 panic("Twin ASIs not supported\n"); 477 if (AsiIsPartialStore(asi)) 478 panic("Partial Store ASIs not supported\n"); 479 if (AsiIsMmu(asi)) 480 goto handleMmuRegAccess; 481 482 if (AsiIsScratchPad(asi)) 483 goto handleScratchRegAccess; 484 } 485 486 if ((!lsuDm && !hpriv) || AsiIsReal(asi)) { 487 real = true; 488 context = 0; 489 }; 490 491 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) { 492 req->setPaddr(req->getVaddr() & PAddrImplMask); 493 return NoFault; 494 } 495 496 e = lookup(req->getVaddr(), part_id, real, context); 497 498 if (e == NULL || !e->valid) { 499 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, 500 vaddr & ~BytesInPageMask | context);
|
| 501 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
|
481 if (real) 482 return new DataRealTranslationMiss; 483 else 484 return new FastDataAccessMMUMiss; 485 486 } 487 488 489 if (write && !e->pte.writable()) { 490 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); 491 return new FastDataAccessProtection; 492 } 493 494 if (e->pte.nofault() && !AsiIsNoFault(asi)) { 495 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); 496 return new DataAccessException; 497 } 498 499 if (e->pte.sideffect()) 500 req->setFlags(req->getFlags() | UNCACHEABLE); 501 502 503 if (!priv && e->pte.priv()) { 504 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 505 return new DataAccessException; 506 } 507 508 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 509 req->getVaddr() & e->pte.size()); 510 return NoFault; 511 /** Normal flow ends here. */ 512 513handleScratchRegAccess: 514 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 515 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 516 return new DataAccessException; 517 } 518handleMmuRegAccess:
| 502 if (real) 503 return new DataRealTranslationMiss; 504 else 505 return new FastDataAccessMMUMiss; 506 507 } 508 509 510 if (write && !e->pte.writable()) { 511 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); 512 return new FastDataAccessProtection; 513 } 514 515 if (e->pte.nofault() && !AsiIsNoFault(asi)) { 516 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); 517 return new DataAccessException; 518 } 519 520 if (e->pte.sideffect()) 521 req->setFlags(req->getFlags() | UNCACHEABLE); 522 523 524 if (!priv && e->pte.priv()) { 525 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 526 return new DataAccessException; 527 } 528 529 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 530 req->getVaddr() & e->pte.size()); 531 return NoFault; 532 /** Normal flow ends here. */ 533 534handleScratchRegAccess: 535 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 536 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 537 return new DataAccessException; 538 } 539handleMmuRegAccess:
|
| 540 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n");
|
519 req->setMmapedIpr(true); 520 req->setPaddr(req->getVaddr()); 521 return NoFault; 522}; 523 524Tick 525DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) 526{ 527 panic("need to implement DTB::doMmuRegRead()\n"); 528} 529 530Tick 531DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) 532{ 533 panic("need to implement DTB::doMmuRegWrite()\n"); 534} 535 536void 537TLB::serialize(std::ostream &os) 538{ 539 panic("Need to implement serialize tlb for SPARC\n"); 540} 541 542void 543TLB::unserialize(Checkpoint *cp, const std::string §ion) 544{ 545 panic("Need to implement unserialize tlb for SPARC\n"); 546} 547 548 549DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) 550 551BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) 552 553 Param<int> size; 554 555END_DECLARE_SIM_OBJECT_PARAMS(ITB) 556 557BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) 558 559 INIT_PARAM_DFLT(size, "TLB size", 48) 560 561END_INIT_SIM_OBJECT_PARAMS(ITB) 562 563 564CREATE_SIM_OBJECT(ITB) 565{ 566 return new ITB(getInstanceName(), size); 567} 568 569REGISTER_SIM_OBJECT("SparcITB", ITB) 570 571BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) 572 573 Param<int> size; 574 575END_DECLARE_SIM_OBJECT_PARAMS(DTB) 576 577BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) 578 579 INIT_PARAM_DFLT(size, "TLB size", 64) 580 581END_INIT_SIM_OBJECT_PARAMS(DTB) 582 583 584CREATE_SIM_OBJECT(DTB) 585{ 586 return new DTB(getInstanceName(), size); 587} 588 589REGISTER_SIM_OBJECT("SparcDTB", DTB) 590}
| 541 req->setMmapedIpr(true); 542 req->setPaddr(req->getVaddr()); 543 return NoFault; 544}; 545 546Tick 547DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) 548{ 549 panic("need to implement DTB::doMmuRegRead()\n"); 550} 551 552Tick 553DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) 554{ 555 panic("need to implement DTB::doMmuRegWrite()\n"); 556} 557 558void 559TLB::serialize(std::ostream &os) 560{ 561 panic("Need to implement serialize tlb for SPARC\n"); 562} 563 564void 565TLB::unserialize(Checkpoint *cp, const std::string §ion) 566{ 567 panic("Need to implement unserialize tlb for SPARC\n"); 568} 569 570 571DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) 572 573BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) 574 575 Param<int> size; 576 577END_DECLARE_SIM_OBJECT_PARAMS(ITB) 578 579BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) 580 581 INIT_PARAM_DFLT(size, "TLB size", 48) 582 583END_INIT_SIM_OBJECT_PARAMS(ITB) 584 585 586CREATE_SIM_OBJECT(ITB) 587{ 588 return new ITB(getInstanceName(), size); 589} 590 591REGISTER_SIM_OBJECT("SparcITB", ITB) 592 593BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) 594 595 Param<int> size; 596 597END_DECLARE_SIM_OBJECT_PARAMS(DTB) 598 599BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) 600 601 INIT_PARAM_DFLT(size, "TLB size", 64) 602 603END_INIT_SIM_OBJECT_PARAMS(DTB) 604 605 606CREATE_SIM_OBJECT(DTB) 607{ 608 return new DTB(getInstanceName(), size); 609} 610 611REGISTER_SIM_OBJECT("SparcDTB", DTB) 612}
|