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;
--- 31 unchanged lines hidden (view full) ---
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), 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
82 cacheValid = false;
83
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 i = lookupTable.insert(new_entry->range, new_entry);
128 assert(i != lookupTable.end());
129
130 // If all entries have there used bit set, clear it on them all, but the
131 // one we just inserted
132 if (usedEntries == size) {
133 clearUsedBits();
--- 80 unchanged lines hidden (view full) ---
214 i = lookupTable.find(tr);
215 if (i != lookupTable.end()) {
216 DPRINTF(IPR, "TLB: Demapped page\n");
217 i->second->valid = false;
218 if (i->second->used) {
219 i->second->used = false;
220 usedEntries--;
221 }
222 lookupTable.erase(i);
223 }
224}
225
226void
227TLB::demapContext(int partition_id, int context_id)
228{
229 int x;
230 DPRINTF(IPR, "TLB: Demapping Context pid=%#d cid=%d\n",
231 partition_id, context_id);
232 cacheValid = false;
233 for (x = 0; x < size; x++) {
234 if (tlb[x].range.contextId == context_id &&
235 tlb[x].range.partitionId == partition_id) {
236 tlb[x].valid = false;
237 if (tlb[x].used) {
238 tlb[x].used = false;
239 usedEntries--;
240 }
241 lookupTable.erase(tlb[x].range);
242 }
243 }
244}
245
246void
247TLB::demapAll(int partition_id)
248{
249 int x;
250 DPRINTF(TLB, "TLB: Demapping All pid=%#d\n", partition_id);
251 cacheValid = false;
252 for (x = 0; x < size; x++) {
253 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) {
254 tlb[x].valid = false;
255 if (tlb[x].used) {
256 tlb[x].used = false;
257 usedEntries--;
258 }
259 lookupTable.erase(tlb[x].range);
260 }
261 }
262}
263
264void
265TLB::invalidateAll()
266{
267 int x;
268 cacheValid = false;
269
270 for (x = 0; x < size; x++) {
271 tlb[x].valid = false;
272 }
273 usedEntries = 0;
274}
275
276uint64_t
277TLB::TteRead(int entry) {
278 assert(entry < size);
279 return tlb[entry].pte();
280}
281
282uint64_t
283TLB::TagRead(int entry) {
284 assert(entry < size);
285 uint64_t tag;
286
287 tag = tlb[entry].range.contextId | tlb[entry].range.va |
288 (uint64_t)tlb[entry].range.partitionId << 61;
289 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0;
290 tag |= (uint64_t)~tlb[entry].pte._size() << 56;
291 return tag;
292}
293
294bool
295TLB::validVirtualAddress(Addr va, bool am)
296{
--- 199 unchanged lines hidden (view full) ---
496 if (hpriv && implicit) {
497 req->setPaddr(vaddr & PAddrImplMask);
498 return NoFault;
499 }
500
501 // Be fast if we can!
502 if (cacheValid && cacheState == tlbdata) {
503 if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size &&
504 cacheEntry[0]->range.va + cacheEntry[0]->range.size >= vaddr) {
505 req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) |
506 vaddr & cacheEntry[0]->pte.size()-1 );
507 return NoFault;
508 }
509 if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size &&
510 cacheEntry[1]->range.va + cacheEntry[1]->range.size >= vaddr) {
511 req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) |
512 vaddr & cacheEntry[1]->pte.size()-1 );
513 return NoFault;
514 }
515 }
516
517 bool red = bits(tlbdata,1,1);
518 bool priv = bits(tlbdata,2,2);
--- 143 unchanged lines hidden (view full) ---
662
663
664 if (!priv && e->pte.priv()) {
665 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
666 return new DataAccessException;
667 }
668
669 // cache translation date for next translation
670 cacheValid = true;
671 cacheState = tlbdata;
672 if (cacheEntry[0] != e && cacheEntry[1] != e) {
673 cacheEntry[1] = cacheEntry[0];
674 cacheEntry[0] = e;
675 cacheAsi[1] = cacheAsi[0];
676 cacheAsi[0] = asi;
677 if (implicit)
678 cacheAsi[0] = (ASI)0;
679 }
680
681 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
682 vaddr & e->pte.size()-1);
683 DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
684 return NoFault;
685 /** Normal flow ends here. */
686
687handleScratchRegAccess:
688 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
689 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
690 return new DataAccessException;
691 }
692 goto regAccessOk;
693
694handleQueueRegAccess:
695 if (!priv && !hpriv) {
696 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
697 return new PrivilegedAction;
698 }
699 if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) {
700 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
701 return new DataAccessException;
702 }
703 goto regAccessOk;
704
705handleSparcErrorRegAccess:
706 if (!hpriv) {
707 if (priv) {
--- 455 unchanged lines hidden ---
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;
--- 31 unchanged lines hidden (view full) ---
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), 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
82 cacheValid = false;
83
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 i = lookupTable.insert(new_entry->range, new_entry);
128 assert(i != lookupTable.end());
129
130 // If all entries have there used bit set, clear it on them all, but the
131 // one we just inserted
132 if (usedEntries == size) {
133 clearUsedBits();
--- 80 unchanged lines hidden (view full) ---
214 i = lookupTable.find(tr);
215 if (i != lookupTable.end()) {
216 DPRINTF(IPR, "TLB: Demapped page\n");
217 i->second->valid = false;
218 if (i->second->used) {
219 i->second->used = false;
220 usedEntries--;
221 }
222 lookupTable.erase(i);
223 }
224}
225
226void
227TLB::demapContext(int partition_id, int context_id)
228{
229 int x;
230 DPRINTF(IPR, "TLB: Demapping Context pid=%#d cid=%d\n",
231 partition_id, context_id);
232 cacheValid = false;
233 for (x = 0; x < size; x++) {
234 if (tlb[x].range.contextId == context_id &&
235 tlb[x].range.partitionId == partition_id) {
236 tlb[x].valid = false;
237 if (tlb[x].used) {
238 tlb[x].used = false;
239 usedEntries--;
240 }
241 lookupTable.erase(tlb[x].range);
242 }
243 }
244}
245
246void
247TLB::demapAll(int partition_id)
248{
249 int x;
250 DPRINTF(TLB, "TLB: Demapping All pid=%#d\n", partition_id);
251 cacheValid = false;
252 for (x = 0; x < size; x++) {
253 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) {
254 tlb[x].valid = false;
255 if (tlb[x].used) {
256 tlb[x].used = false;
257 usedEntries--;
258 }
259 lookupTable.erase(tlb[x].range);
260 }
261 }
262}
263
264void
265TLB::invalidateAll()
266{
267 int x;
268 cacheValid = false;
269
270 for (x = 0; x < size; x++) {
271 tlb[x].valid = false;
272 }
273 usedEntries = 0;
274}
275
276uint64_t
277TLB::TteRead(int entry) {
278 assert(entry < size);
279 return tlb[entry].pte();
280}
281
282uint64_t
283TLB::TagRead(int entry) {
284 assert(entry < size);
285 uint64_t tag;
286
287 tag = tlb[entry].range.contextId | tlb[entry].range.va |
288 (uint64_t)tlb[entry].range.partitionId << 61;
289 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0;
290 tag |= (uint64_t)~tlb[entry].pte._size() << 56;
291 return tag;
292}
293
294bool
295TLB::validVirtualAddress(Addr va, bool am)
296{
--- 199 unchanged lines hidden (view full) ---
496 if (hpriv && implicit) {
497 req->setPaddr(vaddr & PAddrImplMask);
498 return NoFault;
499 }
500
501 // Be fast if we can!
502 if (cacheValid && cacheState == tlbdata) {
503 if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size &&
504 cacheEntry[0]->range.va + cacheEntry[0]->range.size >= vaddr) {
505 req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) |
506 vaddr & cacheEntry[0]->pte.size()-1 );
507 return NoFault;
508 }
509 if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size &&
510 cacheEntry[1]->range.va + cacheEntry[1]->range.size >= vaddr) {
511 req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) |
512 vaddr & cacheEntry[1]->pte.size()-1 );
513 return NoFault;
514 }
515 }
516
517 bool red = bits(tlbdata,1,1);
518 bool priv = bits(tlbdata,2,2);
--- 143 unchanged lines hidden (view full) ---
662
663
664 if (!priv && e->pte.priv()) {
665 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
666 return new DataAccessException;
667 }
668
669 // cache translation date for next translation
670 cacheValid = true;
671 cacheState = tlbdata;
672 if (cacheEntry[0] != e && cacheEntry[1] != e) {
673 cacheEntry[1] = cacheEntry[0];
674 cacheEntry[0] = e;
675 cacheAsi[1] = cacheAsi[0];
676 cacheAsi[0] = asi;
677 if (implicit)
678 cacheAsi[0] = (ASI)0;
679 }
680
681 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
682 vaddr & e->pte.size()-1);
683 DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
684 return NoFault;
685 /** Normal flow ends here. */
686
687handleScratchRegAccess:
688 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
689 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
690 return new DataAccessException;
691 }
692 goto regAccessOk;
693
694handleQueueRegAccess:
695 if (!priv && !hpriv) {
696 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
697 return new PrivilegedAction;
698 }
699 if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) {
700 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
701 return new DataAccessException;
702 }
703 goto regAccessOk;
704
705handleSparcErrorRegAccess:
706 if (!hpriv) {
707 if (priv) {
--- 455 unchanged lines hidden ---