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