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