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" 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)
| 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" 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)
| 48 : SimObject(name), size(s), usedEntries(0), cacheValid(false)
|
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, int entry) 75{ 76 77 78 MapIter i; 79 TlbEntry *new_entry = NULL; 80 int x; 81
| 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, int entry) 75{ 76 77 78 MapIter i; 79 TlbEntry *new_entry = NULL; 80 int x; 81
|
| 82 cacheValid = false; 83
|
82 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d\n", 83 va, PTE.paddr(), partition_id, context_id, (int)real); 84 85 if (entry != -1) { 86 assert(entry < size && entry >= 0); 87 new_entry = &tlb[entry]; 88 } else { 89 for (x = 0; x < size; x++) { 90 if (!tlb[x].valid || !tlb[x].used) { 91 new_entry = &tlb[x]; 92 break; 93 } 94 } 95 } 96 97 // Update the last ently if their all locked 98 if (!new_entry) 99 new_entry = &tlb[size-1]; 100 101 assert(PTE.valid()); 102 new_entry->range.va = va; 103 new_entry->range.size = PTE.size(); 104 new_entry->range.partitionId = partition_id; 105 new_entry->range.contextId = context_id; 106 new_entry->range.real = real; 107 new_entry->pte = PTE; 108 new_entry->used = true;; 109 new_entry->valid = true; 110 usedEntries++; 111 112 113 // Demap any entry that conflicts 114 i = lookupTable.find(new_entry->range); 115 if (i != lookupTable.end()) { 116 i->second->valid = false; 117 if (i->second->used) { 118 i->second->used = false; 119 usedEntries--; 120 } 121 DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n"); 122 lookupTable.erase(i); 123 } 124 125 lookupTable.insert(new_entry->range, new_entry);; 126 127 // If all entries have there used bit set, clear it on them all, but the 128 // one we just inserted 129 if (usedEntries == size) { 130 clearUsedBits(); 131 new_entry->used = true; 132 usedEntries++; 133 } 134 135} 136 137 138TlbEntry* 139TLB::lookup(Addr va, int partition_id, bool real, int context_id) 140{ 141 MapIter i; 142 TlbRange tr; 143 TlbEntry *t; 144 145 DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n", 146 va, partition_id, context_id, real); 147 // Assemble full address structure 148 tr.va = va; 149 tr.size = va + MachineBytes; 150 tr.contextId = context_id; 151 tr.partitionId = partition_id; 152 tr.real = real; 153 154 // Try to find the entry 155 i = lookupTable.find(tr); 156 if (i == lookupTable.end()) { 157 DPRINTF(TLB, "TLB: No valid entry found\n"); 158 return NULL; 159 } 160 161 // Mark the entries used bit and clear other used bits in needed 162 t = i->second; 163 DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(), 164 t->pte.size()); 165 if (!t->used) { 166 t->used = true; 167 usedEntries++; 168 if (usedEntries == size) { 169 clearUsedBits(); 170 t->used = true; 171 usedEntries++; 172 } 173 } 174 175 return t; 176} 177 178void 179TLB::dumpAll() 180{ 181 for (int x = 0; x < size; x++) { 182 if (tlb[x].valid) { 183 DPRINTFN("%4d: %#2x:%#2x %c %#4x %#8x %#8x %#16x\n", 184 x, tlb[x].range.partitionId, tlb[x].range.contextId, 185 tlb[x].range.real ? 'R' : ' ', tlb[x].range.size, 186 tlb[x].range.va, tlb[x].pte.paddr(), tlb[x].pte()); 187 } 188 } 189} 190 191void 192TLB::demapPage(Addr va, int partition_id, bool real, int context_id) 193{ 194 TlbRange tr; 195 MapIter i; 196
| 84 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d\n", 85 va, PTE.paddr(), partition_id, context_id, (int)real); 86 87 if (entry != -1) { 88 assert(entry < size && entry >= 0); 89 new_entry = &tlb[entry]; 90 } else { 91 for (x = 0; x < size; x++) { 92 if (!tlb[x].valid || !tlb[x].used) { 93 new_entry = &tlb[x]; 94 break; 95 } 96 } 97 } 98 99 // Update the last ently if their all locked 100 if (!new_entry) 101 new_entry = &tlb[size-1]; 102 103 assert(PTE.valid()); 104 new_entry->range.va = va; 105 new_entry->range.size = PTE.size(); 106 new_entry->range.partitionId = partition_id; 107 new_entry->range.contextId = context_id; 108 new_entry->range.real = real; 109 new_entry->pte = PTE; 110 new_entry->used = true;; 111 new_entry->valid = true; 112 usedEntries++; 113 114 115 // Demap any entry that conflicts 116 i = lookupTable.find(new_entry->range); 117 if (i != lookupTable.end()) { 118 i->second->valid = false; 119 if (i->second->used) { 120 i->second->used = false; 121 usedEntries--; 122 } 123 DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n"); 124 lookupTable.erase(i); 125 } 126 127 lookupTable.insert(new_entry->range, new_entry);; 128 129 // If all entries have there used bit set, clear it on them all, but the 130 // one we just inserted 131 if (usedEntries == size) { 132 clearUsedBits(); 133 new_entry->used = true; 134 usedEntries++; 135 } 136 137} 138 139 140TlbEntry* 141TLB::lookup(Addr va, int partition_id, bool real, int context_id) 142{ 143 MapIter i; 144 TlbRange tr; 145 TlbEntry *t; 146 147 DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n", 148 va, partition_id, context_id, real); 149 // Assemble full address structure 150 tr.va = va; 151 tr.size = va + MachineBytes; 152 tr.contextId = context_id; 153 tr.partitionId = partition_id; 154 tr.real = real; 155 156 // Try to find the entry 157 i = lookupTable.find(tr); 158 if (i == lookupTable.end()) { 159 DPRINTF(TLB, "TLB: No valid entry found\n"); 160 return NULL; 161 } 162 163 // Mark the entries used bit and clear other used bits in needed 164 t = i->second; 165 DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(), 166 t->pte.size()); 167 if (!t->used) { 168 t->used = true; 169 usedEntries++; 170 if (usedEntries == size) { 171 clearUsedBits(); 172 t->used = true; 173 usedEntries++; 174 } 175 } 176 177 return t; 178} 179 180void 181TLB::dumpAll() 182{ 183 for (int x = 0; x < size; x++) { 184 if (tlb[x].valid) { 185 DPRINTFN("%4d: %#2x:%#2x %c %#4x %#8x %#8x %#16x\n", 186 x, tlb[x].range.partitionId, tlb[x].range.contextId, 187 tlb[x].range.real ? 'R' : ' ', tlb[x].range.size, 188 tlb[x].range.va, tlb[x].pte.paddr(), tlb[x].pte()); 189 } 190 } 191} 192 193void 194TLB::demapPage(Addr va, int partition_id, bool real, int context_id) 195{ 196 TlbRange tr; 197 MapIter i; 198
|
| 199 cacheValid = false; 200
|
197 // Assemble full address structure 198 tr.va = va; 199 tr.size = va + MachineBytes; 200 tr.contextId = context_id; 201 tr.partitionId = partition_id; 202 tr.real = real; 203 204 // Demap any entry that conflicts 205 i = lookupTable.find(tr); 206 if (i != lookupTable.end()) { 207 i->second->valid = false; 208 if (i->second->used) { 209 i->second->used = false; 210 usedEntries--; 211 } 212 lookupTable.erase(i); 213 } 214} 215 216void 217TLB::demapContext(int partition_id, int context_id) 218{ 219 int x;
| 201 // Assemble full address structure 202 tr.va = va; 203 tr.size = va + MachineBytes; 204 tr.contextId = context_id; 205 tr.partitionId = partition_id; 206 tr.real = real; 207 208 // Demap any entry that conflicts 209 i = lookupTable.find(tr); 210 if (i != lookupTable.end()) { 211 i->second->valid = false; 212 if (i->second->used) { 213 i->second->used = false; 214 usedEntries--; 215 } 216 lookupTable.erase(i); 217 } 218} 219 220void 221TLB::demapContext(int partition_id, int context_id) 222{ 223 int x;
|
| 224 cacheValid = false;
|
220 for (x = 0; x < size; x++) { 221 if (tlb[x].range.contextId == context_id && 222 tlb[x].range.partitionId == partition_id) { 223 tlb[x].valid = false; 224 if (tlb[x].used) { 225 tlb[x].used = false; 226 usedEntries--; 227 } 228 lookupTable.erase(tlb[x].range); 229 } 230 } 231} 232 233void 234TLB::demapAll(int partition_id) 235{ 236 int x;
| 225 for (x = 0; x < size; x++) { 226 if (tlb[x].range.contextId == context_id && 227 tlb[x].range.partitionId == partition_id) { 228 tlb[x].valid = false; 229 if (tlb[x].used) { 230 tlb[x].used = false; 231 usedEntries--; 232 } 233 lookupTable.erase(tlb[x].range); 234 } 235 } 236} 237 238void 239TLB::demapAll(int partition_id) 240{ 241 int x;
|
| 242 cacheValid = false;
|
237 for (x = 0; x < size; x++) { 238 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { 239 tlb[x].valid = false; 240 if (tlb[x].used) { 241 tlb[x].used = false; 242 usedEntries--; 243 } 244 lookupTable.erase(tlb[x].range); 245 } 246 } 247} 248 249void 250TLB::invalidateAll() 251{ 252 int x;
| 243 for (x = 0; x < size; x++) { 244 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { 245 tlb[x].valid = false; 246 if (tlb[x].used) { 247 tlb[x].used = false; 248 usedEntries--; 249 } 250 lookupTable.erase(tlb[x].range); 251 } 252 } 253} 254 255void 256TLB::invalidateAll() 257{ 258 int x;
|
| 259 cacheValid = false; 260
|
253 for (x = 0; x < size; x++) { 254 tlb[x].valid = false; 255 } 256 usedEntries = 0; 257} 258 259uint64_t 260TLB::TteRead(int entry) { 261 assert(entry < size); 262 return tlb[entry].pte(); 263} 264 265uint64_t 266TLB::TagRead(int entry) { 267 assert(entry < size); 268 uint64_t tag; 269 270 tag = tlb[entry].range.contextId | tlb[entry].range.va | 271 (uint64_t)tlb[entry].range.partitionId << 61; 272 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 273 tag |= (uint64_t)~tlb[entry].pte._size() << 56; 274 return tag; 275} 276 277bool 278TLB::validVirtualAddress(Addr va, bool am) 279{ 280 if (am) 281 return true; 282 if (va >= StartVAddrHole && va <= EndVAddrHole) 283 return false; 284 return true; 285} 286 287void 288TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, 289 bool se, FaultTypes ft, int asi) 290{ 291 uint64_t sfsr; 292 sfsr = tc->readMiscReg(reg); 293 294 if (sfsr & 0x1) 295 sfsr = 0x3; 296 else 297 sfsr = 1; 298 299 if (write) 300 sfsr |= 1 << 2; 301 sfsr |= ct << 4; 302 if (se) 303 sfsr |= 1 << 6; 304 sfsr |= ft << 7; 305 sfsr |= asi << 16; 306 tc->setMiscRegWithEffect(reg, sfsr); 307} 308 309void 310TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context) 311{ 312 tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0)); 313} 314 315void 316ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct, 317 bool se, FaultTypes ft, int asi) 318{ 319 DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n", 320 (int)write, ct, ft, asi); 321 TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi); 322} 323 324void 325ITB::writeTagAccess(ThreadContext *tc, Addr va, int context) 326{ 327 TLB::writeTagAccess(tc, MISCREG_MMU_ITLB_TAG_ACCESS, va, context); 328} 329 330void 331DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, 332 bool se, FaultTypes ft, int asi) 333{ 334 DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", 335 a, (int)write, ct, ft, asi); 336 TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); 337 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a); 338} 339
| 261 for (x = 0; x < size; x++) { 262 tlb[x].valid = false; 263 } 264 usedEntries = 0; 265} 266 267uint64_t 268TLB::TteRead(int entry) { 269 assert(entry < size); 270 return tlb[entry].pte(); 271} 272 273uint64_t 274TLB::TagRead(int entry) { 275 assert(entry < size); 276 uint64_t tag; 277 278 tag = tlb[entry].range.contextId | tlb[entry].range.va | 279 (uint64_t)tlb[entry].range.partitionId << 61; 280 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 281 tag |= (uint64_t)~tlb[entry].pte._size() << 56; 282 return tag; 283} 284 285bool 286TLB::validVirtualAddress(Addr va, bool am) 287{ 288 if (am) 289 return true; 290 if (va >= StartVAddrHole && va <= EndVAddrHole) 291 return false; 292 return true; 293} 294 295void 296TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, 297 bool se, FaultTypes ft, int asi) 298{ 299 uint64_t sfsr; 300 sfsr = tc->readMiscReg(reg); 301 302 if (sfsr & 0x1) 303 sfsr = 0x3; 304 else 305 sfsr = 1; 306 307 if (write) 308 sfsr |= 1 << 2; 309 sfsr |= ct << 4; 310 if (se) 311 sfsr |= 1 << 6; 312 sfsr |= ft << 7; 313 sfsr |= asi << 16; 314 tc->setMiscRegWithEffect(reg, sfsr); 315} 316 317void 318TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context) 319{ 320 tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0)); 321} 322 323void 324ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct, 325 bool se, FaultTypes ft, int asi) 326{ 327 DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n", 328 (int)write, ct, ft, asi); 329 TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi); 330} 331 332void 333ITB::writeTagAccess(ThreadContext *tc, Addr va, int context) 334{ 335 TLB::writeTagAccess(tc, MISCREG_MMU_ITLB_TAG_ACCESS, va, context); 336} 337 338void 339DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, 340 bool se, FaultTypes ft, int asi) 341{ 342 DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", 343 a, (int)write, ct, ft, asi); 344 TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); 345 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a); 346} 347
|
340 void
| 348void
|
341DTB::writeTagAccess(ThreadContext *tc, Addr va, int context) 342{ 343 TLB::writeTagAccess(tc, MISCREG_MMU_DTLB_TAG_ACCESS, va, context); 344} 345 346 347 348Fault 349ITB::translate(RequestPtr &req, ThreadContext *tc) 350{ 351 uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); 352
| 349DTB::writeTagAccess(ThreadContext *tc, Addr va, int context) 350{ 351 TLB::writeTagAccess(tc, MISCREG_MMU_DTLB_TAG_ACCESS, va, context); 352} 353 354 355 356Fault 357ITB::translate(RequestPtr &req, ThreadContext *tc) 358{ 359 uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); 360
|
| 361 Addr vaddr = req->getVaddr(); 362 TlbEntry *e; 363 364 assert(req->getAsi() == ASI_IMPLICIT); 365 366 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n", 367 vaddr, req->getSize()); 368 369 // Be fast if we can! 370 if (cacheValid && cacheState == tlbdata) { 371 if (cacheEntry) { 372 if (cacheEntry->range.va < vaddr + sizeof(MachInst) && 373 cacheEntry->range.va + cacheEntry->range.size >= vaddr) { 374 req->setPaddr(cacheEntry->pte.paddr() & ~(cacheEntry->pte.size()-1) | 375 vaddr & cacheEntry->pte.size()-1 ); 376 return NoFault; 377 } 378 } else { 379 req->setPaddr(vaddr & PAddrImplMask); 380 return NoFault; 381 } 382 } 383
|
353 bool hpriv = bits(tlbdata,0,0); 354 bool red = bits(tlbdata,1,1); 355 bool priv = bits(tlbdata,2,2); 356 bool addr_mask = bits(tlbdata,3,3); 357 bool lsu_im = bits(tlbdata,4,4); 358 359 int part_id = bits(tlbdata,15,8); 360 int tl = bits(tlbdata,18,16); 361 int pri_context = bits(tlbdata,47,32);
| 384 bool hpriv = bits(tlbdata,0,0); 385 bool red = bits(tlbdata,1,1); 386 bool priv = bits(tlbdata,2,2); 387 bool addr_mask = bits(tlbdata,3,3); 388 bool lsu_im = bits(tlbdata,4,4); 389 390 int part_id = bits(tlbdata,15,8); 391 int tl = bits(tlbdata,18,16); 392 int pri_context = bits(tlbdata,47,32);
|
362 363 Addr vaddr = req->getVaddr();
| |
364 int context; 365 ContextType ct; 366 int asi; 367 bool real = false;
| 393 int context; 394 ContextType ct; 395 int asi; 396 bool real = false;
|
368 TlbEntry *e;
| |
369
| 397
|
370 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n", 371 vaddr, req->getSize());
| |
372 DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsuim:%d part_id: %#X\n", 373 priv, hpriv, red, lsu_im, part_id); 374
| 398 DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsuim:%d part_id: %#X\n", 399 priv, hpriv, red, lsu_im, part_id); 400
|
375 assert(req->getAsi() == ASI_IMPLICIT); 376
| |
377 if (tl > 0) { 378 asi = ASI_N; 379 ct = Nucleus; 380 context = 0; 381 } else { 382 asi = ASI_P; 383 ct = Primary; 384 context = pri_context; 385 } 386 387 if ( hpriv || red ) {
| 401 if (tl > 0) { 402 asi = ASI_N; 403 ct = Nucleus; 404 context = 0; 405 } else { 406 asi = ASI_P; 407 ct = Primary; 408 context = pri_context; 409 } 410 411 if ( hpriv || red ) {
|
388 req->setPaddr(req->getVaddr() & PAddrImplMask);
| 412 cacheValid = true; 413 cacheState = tlbdata; 414 cacheEntry = NULL; 415 req->setPaddr(vaddr & PAddrImplMask);
|
389 return NoFault; 390 } 391
| 416 return NoFault; 417 } 418
|
392 // If the asi is unaligned trap 393 if (vaddr & req->getSize()-1) {
| 419 // If the access is unaligned trap 420 if (vaddr & 0x3) {
|
394 writeSfsr(tc, false, ct, false, OtherFault, asi); 395 return new MemAddressNotAligned; 396 } 397 398 if (addr_mask) 399 vaddr = vaddr & VAddrAMask; 400 401 if (!validVirtualAddress(vaddr, addr_mask)) { 402 writeSfsr(tc, false, ct, false, VaOutOfRange, asi); 403 return new InstructionAccessException; 404 } 405 406 if (!lsu_im) {
| 421 writeSfsr(tc, false, ct, false, OtherFault, asi); 422 return new MemAddressNotAligned; 423 } 424 425 if (addr_mask) 426 vaddr = vaddr & VAddrAMask; 427 428 if (!validVirtualAddress(vaddr, addr_mask)) { 429 writeSfsr(tc, false, ct, false, VaOutOfRange, asi); 430 return new InstructionAccessException; 431 } 432 433 if (!lsu_im) {
|
407 e = lookup(req->getVaddr(), part_id, true);
| 434 e = lookup(vaddr, part_id, true);
|
408 real = true; 409 context = 0; 410 } else { 411 e = lookup(vaddr, part_id, false, context); 412 } 413 414 if (e == NULL || !e->valid) { 415 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, 416 vaddr & ~BytesInPageMask | context); 417 if (real) 418 return new InstructionRealTranslationMiss; 419 else 420 return new FastInstructionAccessMMUMiss; 421 } 422 423 // were not priviledged accesing priv page 424 if (!priv && e->pte.priv()) { 425 writeSfsr(tc, false, ct, false, PrivViolation, asi); 426 return new InstructionAccessException; 427 } 428
| 435 real = true; 436 context = 0; 437 } else { 438 e = lookup(vaddr, part_id, false, context); 439 } 440 441 if (e == NULL || !e->valid) { 442 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, 443 vaddr & ~BytesInPageMask | context); 444 if (real) 445 return new InstructionRealTranslationMiss; 446 else 447 return new FastInstructionAccessMMUMiss; 448 } 449 450 // were not priviledged accesing priv page 451 if (!priv && e->pte.priv()) { 452 writeSfsr(tc, false, ct, false, PrivViolation, asi); 453 return new InstructionAccessException; 454 } 455
|
| 456 // cache translation date for next translation 457 cacheValid = true; 458 cacheState = tlbdata; 459 cacheEntry = e; 460
|
429 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
| 461 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
|
430 req->getVaddr() & e->pte.size()-1 ); 431 DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr());
| 462 vaddr & e->pte.size()-1 ); 463 DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
|
432 return NoFault; 433} 434 435 436 437Fault 438DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 439{ 440 /* @todo this could really use some profiling and fixing to make it faster! */ 441 uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
| 464 return NoFault; 465} 466 467 468 469Fault 470DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 471{ 472 /* @todo this could really use some profiling and fixing to make it faster! */ 473 uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
|
442
| 474 Addr vaddr = req->getVaddr(); 475 Addr size = req->getSize(); 476 ASI asi; 477 asi = (ASI)req->getAsi(); 478 bool implicit = false;
|
443 bool hpriv = bits(tlbdata,0,0);
| 479 bool hpriv = bits(tlbdata,0,0);
|
| 480 481 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", 482 vaddr, size, asi); 483 484 if (asi == ASI_IMPLICIT) 485 implicit = true; 486 487 if (hpriv && implicit) { 488 req->setPaddr(vaddr & PAddrImplMask); 489 return NoFault; 490 } 491 492 // Be fast if we can! 493 if (cacheValid && cacheState == tlbdata) { 494 if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size && 495 cacheEntry[0]->range.va + cacheEntry[0]->range.size >= vaddr) { 496 req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) | 497 vaddr & cacheEntry[0]->pte.size()-1 ); 498 return NoFault; 499 } 500 if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size && 501 cacheEntry[1]->range.va + cacheEntry[1]->range.size >= vaddr) { 502 req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) | 503 vaddr & cacheEntry[1]->pte.size()-1 ); 504 return NoFault; 505 } 506 } 507
|
444 bool red = bits(tlbdata,1,1); 445 bool priv = bits(tlbdata,2,2); 446 bool addr_mask = bits(tlbdata,3,3); 447 bool lsu_dm = bits(tlbdata,5,5); 448 449 int part_id = bits(tlbdata,15,8); 450 int tl = bits(tlbdata,18,16); 451 int pri_context = bits(tlbdata,47,32); 452 int sec_context = bits(tlbdata,47,32); 453
| 508 bool red = bits(tlbdata,1,1); 509 bool priv = bits(tlbdata,2,2); 510 bool addr_mask = bits(tlbdata,3,3); 511 bool lsu_dm = bits(tlbdata,5,5); 512 513 int part_id = bits(tlbdata,15,8); 514 int tl = bits(tlbdata,18,16); 515 int pri_context = bits(tlbdata,47,32); 516 int sec_context = bits(tlbdata,47,32); 517
|
454 bool implicit = false;
| |
455 bool real = false;
| 518 bool real = false;
|
456 Addr vaddr = req->getVaddr(); 457 Addr size = req->getSize();
| |
458 ContextType ct = Primary; 459 int context = 0;
| 519 ContextType ct = Primary; 520 int context = 0;
|
460 ASI asi;
| |
461 462 TlbEntry *e; 463
| 521 522 TlbEntry *e; 523
|
464 asi = (ASI)req->getAsi(); 465 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", 466 vaddr, size, asi);
| |
467 DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n", 468 priv, hpriv, red, lsu_dm, part_id);
| 524 DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n", 525 priv, hpriv, red, lsu_dm, part_id);
|
469 if (asi == ASI_IMPLICIT) 470 implicit = true;
| |
471 472 if (implicit) { 473 if (tl > 0) { 474 asi = ASI_N; 475 ct = Nucleus; 476 context = 0; 477 } else { 478 asi = ASI_P; 479 ct = Primary; 480 context = pri_context; 481 } 482 } else if (!hpriv && !red) { 483 if (tl > 0 || AsiIsNucleus(asi)) { 484 ct = Nucleus; 485 context = 0; 486 } else if (AsiIsSecondary(asi)) { 487 ct = Secondary; 488 context = sec_context; 489 } else { 490 context = pri_context; 491 ct = Primary; //??? 492 } 493 494 // We need to check for priv level/asi priv 495 if (!priv && !AsiIsUnPriv(asi)) { 496 // It appears that context should be Nucleus in these cases? 497 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 498 return new PrivilegedAction; 499 } 500 if (priv && AsiIsHPriv(asi)) { 501 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 502 return new DataAccessException; 503 } 504 505 } else if (hpriv) { 506 if (asi == ASI_P) { 507 ct = Primary; 508 context = pri_context; 509 goto continueDtbFlow; 510 } 511 } 512 513 if (!implicit) { 514 if (AsiIsLittle(asi)) 515 panic("Little Endian ASIs not supported\n"); 516 if (AsiIsBlock(asi)) 517 panic("Block ASIs not supported\n"); 518 if (AsiIsNoFault(asi)) 519 panic("No Fault ASIs not supported\n"); 520 if (write && asi == ASI_LDTX_P) 521 // block init store (like write hint64) 522 goto continueDtbFlow; 523 if (AsiIsTwin(asi)) 524 panic("Twin ASIs not supported\n"); 525 if (AsiIsPartialStore(asi)) 526 panic("Partial Store ASIs not supported\n"); 527 if (AsiIsInterrupt(asi)) 528 panic("Interrupt ASIs not supported\n"); 529 530 if (AsiIsMmu(asi)) 531 goto handleMmuRegAccess; 532 if (AsiIsScratchPad(asi)) 533 goto handleScratchRegAccess; 534 if (AsiIsQueue(asi)) 535 goto handleQueueRegAccess; 536 if (AsiIsSparcError(asi)) 537 goto handleSparcErrorRegAccess; 538 539 if (!AsiIsReal(asi) && !AsiIsNucleus(asi)) 540 panic("Accessing ASI %#X. Should we?\n", asi); 541 } 542 543continueDtbFlow: 544 // If the asi is unaligned trap 545 if (vaddr & size-1) { 546 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); 547 return new MemAddressNotAligned; 548 } 549 550 if (addr_mask) 551 vaddr = vaddr & VAddrAMask; 552 553 if (!validVirtualAddress(vaddr, addr_mask)) { 554 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi); 555 return new DataAccessException; 556 } 557 558 559 if ((!lsu_dm && !hpriv) || AsiIsReal(asi)) { 560 real = true; 561 context = 0; 562 }; 563 564 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
| 526 527 if (implicit) { 528 if (tl > 0) { 529 asi = ASI_N; 530 ct = Nucleus; 531 context = 0; 532 } else { 533 asi = ASI_P; 534 ct = Primary; 535 context = pri_context; 536 } 537 } else if (!hpriv && !red) { 538 if (tl > 0 || AsiIsNucleus(asi)) { 539 ct = Nucleus; 540 context = 0; 541 } else if (AsiIsSecondary(asi)) { 542 ct = Secondary; 543 context = sec_context; 544 } else { 545 context = pri_context; 546 ct = Primary; //??? 547 } 548 549 // We need to check for priv level/asi priv 550 if (!priv && !AsiIsUnPriv(asi)) { 551 // It appears that context should be Nucleus in these cases? 552 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 553 return new PrivilegedAction; 554 } 555 if (priv && AsiIsHPriv(asi)) { 556 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 557 return new DataAccessException; 558 } 559 560 } else if (hpriv) { 561 if (asi == ASI_P) { 562 ct = Primary; 563 context = pri_context; 564 goto continueDtbFlow; 565 } 566 } 567 568 if (!implicit) { 569 if (AsiIsLittle(asi)) 570 panic("Little Endian ASIs not supported\n"); 571 if (AsiIsBlock(asi)) 572 panic("Block ASIs not supported\n"); 573 if (AsiIsNoFault(asi)) 574 panic("No Fault ASIs not supported\n"); 575 if (write && asi == ASI_LDTX_P) 576 // block init store (like write hint64) 577 goto continueDtbFlow; 578 if (AsiIsTwin(asi)) 579 panic("Twin ASIs not supported\n"); 580 if (AsiIsPartialStore(asi)) 581 panic("Partial Store ASIs not supported\n"); 582 if (AsiIsInterrupt(asi)) 583 panic("Interrupt ASIs not supported\n"); 584 585 if (AsiIsMmu(asi)) 586 goto handleMmuRegAccess; 587 if (AsiIsScratchPad(asi)) 588 goto handleScratchRegAccess; 589 if (AsiIsQueue(asi)) 590 goto handleQueueRegAccess; 591 if (AsiIsSparcError(asi)) 592 goto handleSparcErrorRegAccess; 593 594 if (!AsiIsReal(asi) && !AsiIsNucleus(asi)) 595 panic("Accessing ASI %#X. Should we?\n", asi); 596 } 597 598continueDtbFlow: 599 // If the asi is unaligned trap 600 if (vaddr & size-1) { 601 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); 602 return new MemAddressNotAligned; 603 } 604 605 if (addr_mask) 606 vaddr = vaddr & VAddrAMask; 607 608 if (!validVirtualAddress(vaddr, addr_mask)) { 609 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi); 610 return new DataAccessException; 611 } 612 613 614 if ((!lsu_dm && !hpriv) || AsiIsReal(asi)) { 615 real = true; 616 context = 0; 617 }; 618 619 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
|
565 req->setPaddr(req->getVaddr() & PAddrImplMask);
| 620 req->setPaddr(vaddr & PAddrImplMask);
|
566 return NoFault; 567 } 568
| 621 return NoFault; 622 } 623
|
569 e = lookup(req->getVaddr(), part_id, real, context);
| 624 e = lookup(vaddr, part_id, real, context);
|
570 571 if (e == NULL || !e->valid) { 572 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, 573 vaddr & ~BytesInPageMask | context); 574 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n"); 575 if (real) 576 return new DataRealTranslationMiss; 577 else 578 return new FastDataAccessMMUMiss; 579 580 } 581 582 583 if (write && !e->pte.writable()) { 584 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); 585 return new FastDataAccessProtection; 586 } 587 588 if (e->pte.nofault() && !AsiIsNoFault(asi)) { 589 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); 590 return new DataAccessException; 591 } 592 593 if (e->pte.sideffect()) 594 req->setFlags(req->getFlags() | UNCACHEABLE); 595 596 597 if (!priv && e->pte.priv()) { 598 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 599 return new DataAccessException; 600 } 601
| 625 626 if (e == NULL || !e->valid) { 627 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, 628 vaddr & ~BytesInPageMask | context); 629 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n"); 630 if (real) 631 return new DataRealTranslationMiss; 632 else 633 return new FastDataAccessMMUMiss; 634 635 } 636 637 638 if (write && !e->pte.writable()) { 639 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); 640 return new FastDataAccessProtection; 641 } 642 643 if (e->pte.nofault() && !AsiIsNoFault(asi)) { 644 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); 645 return new DataAccessException; 646 } 647 648 if (e->pte.sideffect()) 649 req->setFlags(req->getFlags() | UNCACHEABLE); 650 651 652 if (!priv && e->pte.priv()) { 653 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 654 return new DataAccessException; 655 } 656
|
| 657 // cache translation date for next translation 658 cacheValid = true; 659 cacheState = tlbdata; 660 if (cacheEntry[0] != e && cacheEntry[1] != e) { 661 cacheEntry[1] = cacheEntry[0]; 662 cacheEntry[0] = e; 663 cacheAsi[1] = cacheAsi[0]; 664 cacheAsi[0] = asi; 665 if (implicit) 666 cacheAsi[0] = (ASI)0; 667 } 668
|
602 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
| 669 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
|
603 req->getVaddr() & e->pte.size()-1); 604 DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr());
| 670 vaddr & e->pte.size()-1); 671 DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
|
605 return NoFault; 606 /** Normal flow ends here. */ 607 608handleScratchRegAccess: 609 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 610 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 611 return new DataAccessException; 612 } 613 goto regAccessOk; 614 615handleQueueRegAccess: 616 if (!priv && !hpriv) { 617 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 618 return new PrivilegedAction; 619 } 620 if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { 621 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 622 return new DataAccessException; 623 } 624 goto regAccessOk; 625 626handleSparcErrorRegAccess: 627 if (!hpriv) { 628 if (priv) { 629 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 630 return new DataAccessException; 631 } else { 632 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 633 return new PrivilegedAction; 634 } 635 } 636 goto regAccessOk; 637 638 639regAccessOk: 640handleMmuRegAccess: 641 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n"); 642 req->setMmapedIpr(true); 643 req->setPaddr(req->getVaddr()); 644 return NoFault; 645}; 646 647Tick 648DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) 649{ 650 Addr va = pkt->getAddr(); 651 ASI asi = (ASI)pkt->req->getAsi(); 652 uint64_t temp, data; 653 uint64_t tsbtemp, cnftemp; 654 655 DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", 656 (uint32_t)pkt->req->getAsi(), pkt->getAddr()); 657 658 switch (asi) { 659 case ASI_LSU_CONTROL_REG: 660 assert(va == 0); 661 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL)); 662 break; 663 case ASI_MMU: 664 switch (va) { 665 case 0x8: 666 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT)); 667 break; 668 case 0x10: 669 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT)); 670 break; 671 default: 672 goto doMmuReadError; 673 } 674 break; 675 case ASI_QUEUE: 676 pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 677 (va >> 4) - 0x3c)); 678 break; 679 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 680 assert(va == 0); 681 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); 682 break; 683 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 684 assert(va == 0); 685 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); 686 break; 687 case ASI_DMMU_CTXT_ZERO_CONFIG: 688 assert(va == 0); 689 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG)); 690 break; 691 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 692 assert(va == 0); 693 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); 694 break; 695 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 696 assert(va == 0); 697 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); 698 break; 699 case ASI_IMMU_CTXT_ZERO_CONFIG: 700 assert(va == 0); 701 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG)); 702 break; 703 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 704 assert(va == 0); 705 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); 706 break; 707 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 708 assert(va == 0); 709 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); 710 break; 711 case ASI_DMMU_CTXT_NONZERO_CONFIG: 712 assert(va == 0); 713 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); 714 break; 715 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 716 assert(va == 0); 717 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); 718 break; 719 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 720 assert(va == 0); 721 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); 722 break; 723 case ASI_IMMU_CTXT_NONZERO_CONFIG: 724 assert(va == 0); 725 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); 726 break; 727 case ASI_SPARC_ERROR_STATUS_REG: 728 warn("returning 0 for SPARC ERROR regsiter read\n"); 729 pkt->set(0); 730 break; 731 case ASI_HYP_SCRATCHPAD: 732 case ASI_SCRATCHPAD: 733 pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3))); 734 break; 735 case ASI_IMMU: 736 switch (va) { 737 case 0x0: 738 temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); 739 pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); 740 break; 741 case 0x30: 742 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); 743 break; 744 default: 745 goto doMmuReadError; 746 } 747 break; 748 case ASI_DMMU: 749 switch (va) { 750 case 0x0: 751 temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 752 pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); 753 break; 754 case 0x30: 755 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); 756 break; 757 case 0x80: 758 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID)); 759 break; 760 default: 761 goto doMmuReadError; 762 } 763 break; 764 case ASI_DMMU_TSB_PS0_PTR_REG: 765 temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 766 if (bits(temp,12,0) == 0) { 767 tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0); 768 cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); 769 } else { 770 tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0); 771 cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); 772 } 773 data = mbits(tsbtemp,63,13); 774 data |= temp >> (9 + bits(cnftemp,2,0) * 3) & 775 mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
| 672 return NoFault; 673 /** Normal flow ends here. */ 674 675handleScratchRegAccess: 676 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 677 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 678 return new DataAccessException; 679 } 680 goto regAccessOk; 681 682handleQueueRegAccess: 683 if (!priv && !hpriv) { 684 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 685 return new PrivilegedAction; 686 } 687 if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { 688 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 689 return new DataAccessException; 690 } 691 goto regAccessOk; 692 693handleSparcErrorRegAccess: 694 if (!hpriv) { 695 if (priv) { 696 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 697 return new DataAccessException; 698 } else { 699 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 700 return new PrivilegedAction; 701 } 702 } 703 goto regAccessOk; 704 705 706regAccessOk: 707handleMmuRegAccess: 708 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n"); 709 req->setMmapedIpr(true); 710 req->setPaddr(req->getVaddr()); 711 return NoFault; 712}; 713 714Tick 715DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) 716{ 717 Addr va = pkt->getAddr(); 718 ASI asi = (ASI)pkt->req->getAsi(); 719 uint64_t temp, data; 720 uint64_t tsbtemp, cnftemp; 721 722 DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", 723 (uint32_t)pkt->req->getAsi(), pkt->getAddr()); 724 725 switch (asi) { 726 case ASI_LSU_CONTROL_REG: 727 assert(va == 0); 728 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL)); 729 break; 730 case ASI_MMU: 731 switch (va) { 732 case 0x8: 733 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT)); 734 break; 735 case 0x10: 736 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT)); 737 break; 738 default: 739 goto doMmuReadError; 740 } 741 break; 742 case ASI_QUEUE: 743 pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 744 (va >> 4) - 0x3c)); 745 break; 746 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 747 assert(va == 0); 748 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); 749 break; 750 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 751 assert(va == 0); 752 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); 753 break; 754 case ASI_DMMU_CTXT_ZERO_CONFIG: 755 assert(va == 0); 756 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG)); 757 break; 758 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 759 assert(va == 0); 760 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); 761 break; 762 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 763 assert(va == 0); 764 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); 765 break; 766 case ASI_IMMU_CTXT_ZERO_CONFIG: 767 assert(va == 0); 768 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG)); 769 break; 770 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 771 assert(va == 0); 772 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); 773 break; 774 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 775 assert(va == 0); 776 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); 777 break; 778 case ASI_DMMU_CTXT_NONZERO_CONFIG: 779 assert(va == 0); 780 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); 781 break; 782 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 783 assert(va == 0); 784 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); 785 break; 786 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 787 assert(va == 0); 788 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); 789 break; 790 case ASI_IMMU_CTXT_NONZERO_CONFIG: 791 assert(va == 0); 792 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); 793 break; 794 case ASI_SPARC_ERROR_STATUS_REG: 795 warn("returning 0 for SPARC ERROR regsiter read\n"); 796 pkt->set(0); 797 break; 798 case ASI_HYP_SCRATCHPAD: 799 case ASI_SCRATCHPAD: 800 pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3))); 801 break; 802 case ASI_IMMU: 803 switch (va) { 804 case 0x0: 805 temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); 806 pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); 807 break; 808 case 0x30: 809 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); 810 break; 811 default: 812 goto doMmuReadError; 813 } 814 break; 815 case ASI_DMMU: 816 switch (va) { 817 case 0x0: 818 temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 819 pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); 820 break; 821 case 0x30: 822 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); 823 break; 824 case 0x80: 825 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID)); 826 break; 827 default: 828 goto doMmuReadError; 829 } 830 break; 831 case ASI_DMMU_TSB_PS0_PTR_REG: 832 temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 833 if (bits(temp,12,0) == 0) { 834 tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0); 835 cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); 836 } else { 837 tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0); 838 cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); 839 } 840 data = mbits(tsbtemp,63,13); 841 data |= temp >> (9 + bits(cnftemp,2,0) * 3) & 842 mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
|
776 warn("base addr: %#X tag access: %#X page size: %#X tsb size: %#X\n", 777 bits(tsbtemp,63,13), temp, bits(cnftemp,2,0), bits(tsbtemp,3,0));
| |
778 pkt->set(data); 779 break; 780 case ASI_DMMU_TSB_PS1_PTR_REG: 781 temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 782 if (bits(temp,12,0) == 0) { 783 tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1); 784 cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); 785 } else { 786 tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1); 787 cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); 788 } 789 data = mbits(tsbtemp,63,13); 790 if (bits(tsbtemp,12,12)) 791 data |= ULL(1) << (13+bits(tsbtemp,3,0)); 792 data |= temp >> (9 + bits(cnftemp,2,0) * 3) & 793 mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); 794 pkt->set(data); 795 break; 796 797 default: 798doMmuReadError: 799 panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", 800 (uint32_t)asi, va); 801 } 802 pkt->result = Packet::Success; 803 return tc->getCpuPtr()->cycles(1); 804} 805 806Tick 807DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) 808{ 809 uint64_t data = gtoh(pkt->get<uint64_t>()); 810 Addr va = pkt->getAddr(); 811 ASI asi = (ASI)pkt->req->getAsi(); 812 813 Addr ta_insert; 814 Addr va_insert; 815 Addr ct_insert; 816 int part_insert; 817 int entry_insert = -1; 818 bool real_insert; 819 PageTableEntry pte; 820 821 DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n", 822 (uint32_t)asi, va, data); 823 824 switch (asi) { 825 case ASI_LSU_CONTROL_REG: 826 assert(va == 0); 827 tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data); 828 break; 829 case ASI_MMU: 830 switch (va) { 831 case 0x8: 832 tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data); 833 break; 834 case 0x10: 835 tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data); 836 break; 837 default: 838 goto doMmuWriteError; 839 } 840 break; 841 case ASI_QUEUE: 842 assert(mbits(data,13,6) == data); 843 tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 844 (va >> 4) - 0x3c, data); 845 break; 846 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 847 assert(va == 0); 848 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data); 849 break; 850 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 851 assert(va == 0); 852 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data); 853 break; 854 case ASI_DMMU_CTXT_ZERO_CONFIG: 855 assert(va == 0); 856 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data); 857 break; 858 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 859 assert(va == 0); 860 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data); 861 break; 862 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 863 assert(va == 0); 864 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data); 865 break; 866 case ASI_IMMU_CTXT_ZERO_CONFIG: 867 assert(va == 0); 868 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data); 869 break; 870 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 871 assert(va == 0); 872 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data); 873 break; 874 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 875 assert(va == 0); 876 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data); 877 break; 878 case ASI_DMMU_CTXT_NONZERO_CONFIG: 879 assert(va == 0); 880 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data); 881 break; 882 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 883 assert(va == 0); 884 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data); 885 break; 886 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 887 assert(va == 0); 888 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data); 889 break; 890 case ASI_IMMU_CTXT_NONZERO_CONFIG: 891 assert(va == 0); 892 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data); 893 break; 894 case ASI_SPARC_ERROR_EN_REG: 895 case ASI_SPARC_ERROR_STATUS_REG: 896 warn("Ignoring write to SPARC ERROR regsiter\n"); 897 break; 898 case ASI_HYP_SCRATCHPAD: 899 case ASI_SCRATCHPAD: 900 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); 901 break; 902 case ASI_IMMU: 903 switch (va) { 904 case 0x30: 905 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data); 906 break; 907 default: 908 goto doMmuWriteError; 909 } 910 break; 911 case ASI_ITLB_DATA_ACCESS_REG: 912 entry_insert = bits(va, 8,3); 913 case ASI_ITLB_DATA_IN_REG: 914 assert(entry_insert != -1 || mbits(va,10,9) == va); 915 ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); 916 va_insert = mbits(ta_insert, 63,13); 917 ct_insert = mbits(ta_insert, 12,0); 918 part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); 919 real_insert = bits(va, 9,9); 920 pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : 921 PageTableEntry::sun4u); 922 tc->getITBPtr()->insert(va_insert, part_insert, ct_insert, real_insert, 923 pte, entry_insert); 924 break; 925 case ASI_DTLB_DATA_ACCESS_REG: 926 entry_insert = bits(va, 8,3); 927 case ASI_DTLB_DATA_IN_REG: 928 assert(entry_insert != -1 || mbits(va,10,9) == va); 929 ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 930 va_insert = mbits(ta_insert, 63,13); 931 ct_insert = mbits(ta_insert, 12,0); 932 part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); 933 real_insert = bits(va, 9,9); 934 pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : 935 PageTableEntry::sun4u); 936 insert(va_insert, part_insert, ct_insert, real_insert, pte, entry_insert); 937 break; 938 case ASI_DMMU: 939 switch (va) { 940 case 0x30: 941 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data); 942 break; 943 case 0x80: 944 tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data); 945 break; 946 default: 947 goto doMmuWriteError; 948 } 949 break; 950 default: 951doMmuWriteError: 952 panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", 953 (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); 954 } 955 pkt->result = Packet::Success; 956 return tc->getCpuPtr()->cycles(1); 957} 958 959void 960TLB::serialize(std::ostream &os) 961{ 962 panic("Need to implement serialize tlb for SPARC\n"); 963} 964 965void 966TLB::unserialize(Checkpoint *cp, const std::string §ion) 967{ 968 panic("Need to implement unserialize tlb for SPARC\n"); 969} 970 971 972DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) 973 974BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) 975 976 Param<int> size; 977 978END_DECLARE_SIM_OBJECT_PARAMS(ITB) 979 980BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) 981 982 INIT_PARAM_DFLT(size, "TLB size", 48) 983 984END_INIT_SIM_OBJECT_PARAMS(ITB) 985 986 987CREATE_SIM_OBJECT(ITB) 988{ 989 return new ITB(getInstanceName(), size); 990} 991 992REGISTER_SIM_OBJECT("SparcITB", ITB) 993 994BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) 995 996 Param<int> size; 997 998END_DECLARE_SIM_OBJECT_PARAMS(DTB) 999 1000BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) 1001 1002 INIT_PARAM_DFLT(size, "TLB size", 64) 1003 1004END_INIT_SIM_OBJECT_PARAMS(DTB) 1005 1006 1007CREATE_SIM_OBJECT(DTB) 1008{ 1009 return new DTB(getInstanceName(), size); 1010} 1011 1012REGISTER_SIM_OBJECT("SparcDTB", DTB) 1013}
| 843 pkt->set(data); 844 break; 845 case ASI_DMMU_TSB_PS1_PTR_REG: 846 temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 847 if (bits(temp,12,0) == 0) { 848 tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1); 849 cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); 850 } else { 851 tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1); 852 cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); 853 } 854 data = mbits(tsbtemp,63,13); 855 if (bits(tsbtemp,12,12)) 856 data |= ULL(1) << (13+bits(tsbtemp,3,0)); 857 data |= temp >> (9 + bits(cnftemp,2,0) * 3) & 858 mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); 859 pkt->set(data); 860 break; 861 862 default: 863doMmuReadError: 864 panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", 865 (uint32_t)asi, va); 866 } 867 pkt->result = Packet::Success; 868 return tc->getCpuPtr()->cycles(1); 869} 870 871Tick 872DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) 873{ 874 uint64_t data = gtoh(pkt->get<uint64_t>()); 875 Addr va = pkt->getAddr(); 876 ASI asi = (ASI)pkt->req->getAsi(); 877 878 Addr ta_insert; 879 Addr va_insert; 880 Addr ct_insert; 881 int part_insert; 882 int entry_insert = -1; 883 bool real_insert; 884 PageTableEntry pte; 885 886 DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n", 887 (uint32_t)asi, va, data); 888 889 switch (asi) { 890 case ASI_LSU_CONTROL_REG: 891 assert(va == 0); 892 tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data); 893 break; 894 case ASI_MMU: 895 switch (va) { 896 case 0x8: 897 tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data); 898 break; 899 case 0x10: 900 tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data); 901 break; 902 default: 903 goto doMmuWriteError; 904 } 905 break; 906 case ASI_QUEUE: 907 assert(mbits(data,13,6) == data); 908 tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 909 (va >> 4) - 0x3c, data); 910 break; 911 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 912 assert(va == 0); 913 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data); 914 break; 915 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 916 assert(va == 0); 917 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data); 918 break; 919 case ASI_DMMU_CTXT_ZERO_CONFIG: 920 assert(va == 0); 921 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data); 922 break; 923 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 924 assert(va == 0); 925 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data); 926 break; 927 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 928 assert(va == 0); 929 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data); 930 break; 931 case ASI_IMMU_CTXT_ZERO_CONFIG: 932 assert(va == 0); 933 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data); 934 break; 935 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 936 assert(va == 0); 937 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data); 938 break; 939 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 940 assert(va == 0); 941 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data); 942 break; 943 case ASI_DMMU_CTXT_NONZERO_CONFIG: 944 assert(va == 0); 945 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data); 946 break; 947 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 948 assert(va == 0); 949 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data); 950 break; 951 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 952 assert(va == 0); 953 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data); 954 break; 955 case ASI_IMMU_CTXT_NONZERO_CONFIG: 956 assert(va == 0); 957 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data); 958 break; 959 case ASI_SPARC_ERROR_EN_REG: 960 case ASI_SPARC_ERROR_STATUS_REG: 961 warn("Ignoring write to SPARC ERROR regsiter\n"); 962 break; 963 case ASI_HYP_SCRATCHPAD: 964 case ASI_SCRATCHPAD: 965 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); 966 break; 967 case ASI_IMMU: 968 switch (va) { 969 case 0x30: 970 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data); 971 break; 972 default: 973 goto doMmuWriteError; 974 } 975 break; 976 case ASI_ITLB_DATA_ACCESS_REG: 977 entry_insert = bits(va, 8,3); 978 case ASI_ITLB_DATA_IN_REG: 979 assert(entry_insert != -1 || mbits(va,10,9) == va); 980 ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); 981 va_insert = mbits(ta_insert, 63,13); 982 ct_insert = mbits(ta_insert, 12,0); 983 part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); 984 real_insert = bits(va, 9,9); 985 pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : 986 PageTableEntry::sun4u); 987 tc->getITBPtr()->insert(va_insert, part_insert, ct_insert, real_insert, 988 pte, entry_insert); 989 break; 990 case ASI_DTLB_DATA_ACCESS_REG: 991 entry_insert = bits(va, 8,3); 992 case ASI_DTLB_DATA_IN_REG: 993 assert(entry_insert != -1 || mbits(va,10,9) == va); 994 ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 995 va_insert = mbits(ta_insert, 63,13); 996 ct_insert = mbits(ta_insert, 12,0); 997 part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); 998 real_insert = bits(va, 9,9); 999 pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : 1000 PageTableEntry::sun4u); 1001 insert(va_insert, part_insert, ct_insert, real_insert, pte, entry_insert); 1002 break; 1003 case ASI_DMMU: 1004 switch (va) { 1005 case 0x30: 1006 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data); 1007 break; 1008 case 0x80: 1009 tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data); 1010 break; 1011 default: 1012 goto doMmuWriteError; 1013 } 1014 break; 1015 default: 1016doMmuWriteError: 1017 panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", 1018 (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); 1019 } 1020 pkt->result = Packet::Success; 1021 return tc->getCpuPtr()->cycles(1); 1022} 1023 1024void 1025TLB::serialize(std::ostream &os) 1026{ 1027 panic("Need to implement serialize tlb for SPARC\n"); 1028} 1029 1030void 1031TLB::unserialize(Checkpoint *cp, const std::string §ion) 1032{ 1033 panic("Need to implement unserialize tlb for SPARC\n"); 1034} 1035 1036 1037DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) 1038 1039BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) 1040 1041 Param<int> size; 1042 1043END_DECLARE_SIM_OBJECT_PARAMS(ITB) 1044 1045BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) 1046 1047 INIT_PARAM_DFLT(size, "TLB size", 48) 1048 1049END_INIT_SIM_OBJECT_PARAMS(ITB) 1050 1051 1052CREATE_SIM_OBJECT(ITB) 1053{ 1054 return new ITB(getInstanceName(), size); 1055} 1056 1057REGISTER_SIM_OBJECT("SparcITB", ITB) 1058 1059BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) 1060 1061 Param<int> size; 1062 1063END_DECLARE_SIM_OBJECT_PARAMS(DTB) 1064 1065BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) 1066 1067 INIT_PARAM_DFLT(size, "TLB size", 64) 1068 1069END_INIT_SIM_OBJECT_PARAMS(DTB) 1070 1071 1072CREATE_SIM_OBJECT(DTB) 1073{ 1074 return new DTB(getInstanceName(), size); 1075} 1076 1077REGISTER_SIM_OBJECT("SparcDTB", DTB) 1078}
|