tlb.cc (3832:49c95a73e29c) tlb.cc (3833:b5faabcf350e)
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)
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 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
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;
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;
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;
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
340 void
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{
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)
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 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
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;
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;
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;
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
340 void
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 hpstate = tc->readMiscReg(MISCREG_HPSTATE);
352 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
353 bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1;
354 uint64_t tl = tc->readMiscReg(MISCREG_TL);
355 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
356 bool addr_mask = pstate >> 3 & 0x1;
357 bool priv = pstate >> 2 & 0x1;
351 uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
352
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);
362
358 Addr vaddr = req->getVaddr();
359 int context;
360 ContextType ct;
361 int asi;
362 bool real = false;
363 TlbEntry *e;
364
365 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n",
366 vaddr, req->getSize());
363 Addr vaddr = req->getVaddr();
364 int context;
365 ContextType ct;
366 int asi;
367 bool real = false;
368 TlbEntry *e;
369
370 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n",
371 vaddr, req->getSize());
367 DPRINTF(TLB, "TLB: pstate: %#X hpstate: %#X lsudm: %#X part_id: %#X\n",
368 pstate, hpstate, lsuIm, part_id);
372 DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsuim:%d part_id: %#X\n",
373 priv, hpriv, red, lsu_im, part_id);
369
370 assert(req->getAsi() == ASI_IMPLICIT);
371
372 if (tl > 0) {
373 asi = ASI_N;
374 ct = Nucleus;
375 context = 0;
376 } else {
377 asi = ASI_P;
378 ct = Primary;
374
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;
379 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
384 context = pri_context;
380 }
381
385 }
386
382 if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) {
387 if ( hpriv || red ) {
383 req->setPaddr(req->getVaddr() & PAddrImplMask);
384 return NoFault;
385 }
386
387 // If the asi is unaligned trap
388 if (vaddr & req->getSize()-1) {
389 writeSfsr(tc, false, ct, false, OtherFault, asi);
390 return new MemAddressNotAligned;
391 }
392
393 if (addr_mask)
394 vaddr = vaddr & VAddrAMask;
395
396 if (!validVirtualAddress(vaddr, addr_mask)) {
397 writeSfsr(tc, false, ct, false, VaOutOfRange, asi);
398 return new InstructionAccessException;
399 }
400
388 req->setPaddr(req->getVaddr() & PAddrImplMask);
389 return NoFault;
390 }
391
392 // If the asi is unaligned trap
393 if (vaddr & req->getSize()-1) {
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
401 if (!lsuIm) {
406 if (!lsu_im) {
402 e = lookup(req->getVaddr(), part_id, true);
403 real = true;
404 context = 0;
405 } else {
406 e = lookup(vaddr, part_id, false, context);
407 }
408
409 if (e == NULL || !e->valid) {
410 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS,
411 vaddr & ~BytesInPageMask | context);
412 if (real)
413 return new InstructionRealTranslationMiss;
414 else
415 return new FastInstructionAccessMMUMiss;
416 }
417
418 // were not priviledged accesing priv page
419 if (!priv && e->pte.priv()) {
420 writeSfsr(tc, false, ct, false, PrivViolation, asi);
421 return new InstructionAccessException;
422 }
423
424 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
425 req->getVaddr() & e->pte.size()-1 );
426 DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr());
427 return NoFault;
428}
429
430
431
432Fault
433DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
434{
435 /* @todo this could really use some profiling and fixing to make it faster! */
407 e = lookup(req->getVaddr(), 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
429 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());
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! */
436 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
437 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
438 bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1;
439 uint64_t tl = tc->readMiscReg(MISCREG_TL);
440 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
441 bool hpriv = hpstate >> 2 & 0x1;
442 bool red = hpstate >> 5 >> 0x1;
443 bool addr_mask = pstate >> 3 & 0x1;
444 bool priv = pstate >> 2 & 0x1;
441 uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
442
443 bool hpriv = bits(tlbdata,0,0);
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
445 bool implicit = false;
446 bool real = false;
447 Addr vaddr = req->getVaddr();
448 Addr size = req->getSize();
449 ContextType ct = Primary;
450 int context = 0;
451 ASI asi;
452
453 TlbEntry *e;
454
455 asi = (ASI)req->getAsi();
456 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
457 vaddr, size, asi);
454 bool implicit = false;
455 bool real = false;
456 Addr vaddr = req->getVaddr();
457 Addr size = req->getSize();
458 ContextType ct = Primary;
459 int context = 0;
460 ASI asi;
461
462 TlbEntry *e;
463
464 asi = (ASI)req->getAsi();
465 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
466 vaddr, size, asi);
458 DPRINTF(TLB, "TLB: pstate: %#X hpstate: %#X lsudm: %#X part_id: %#X\n",
459 pstate, hpstate, lsuDm, part_id);
467 DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n",
468 priv, hpriv, red, lsu_dm, part_id);
460 if (asi == ASI_IMPLICIT)
461 implicit = true;
462
463 if (implicit) {
464 if (tl > 0) {
465 asi = ASI_N;
466 ct = Nucleus;
467 context = 0;
468 } else {
469 asi = ASI_P;
470 ct = Primary;
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;
471 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
480 context = pri_context;
472 }
473 } else if (!hpriv && !red) {
474 if (tl > 0 || AsiIsNucleus(asi)) {
475 ct = Nucleus;
476 context = 0;
477 } else if (AsiIsSecondary(asi)) {
478 ct = Secondary;
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;
479 context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT);
488 context = sec_context;
480 } else {
489 } else {
481 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
490 context = pri_context;
482 ct = Primary; //???
483 }
484
485 // We need to check for priv level/asi priv
486 if (!priv && !AsiIsUnPriv(asi)) {
487 // It appears that context should be Nucleus in these cases?
488 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
489 return new PrivilegedAction;
490 }
491 if (priv && AsiIsHPriv(asi)) {
492 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
493 return new DataAccessException;
494 }
495
496 } else if (hpriv) {
497 if (asi == ASI_P) {
498 ct = Primary;
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;
499 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
508 context = pri_context;
500 goto continueDtbFlow;
501 }
502 }
503
504 if (!implicit) {
505 if (AsiIsLittle(asi))
506 panic("Little Endian ASIs not supported\n");
507 if (AsiIsBlock(asi))
508 panic("Block ASIs not supported\n");
509 if (AsiIsNoFault(asi))
510 panic("No Fault ASIs not supported\n");
511 if (write && asi == ASI_LDTX_P)
512 // block init store (like write hint64)
513 goto continueDtbFlow;
514 if (AsiIsTwin(asi))
515 panic("Twin ASIs not supported\n");
516 if (AsiIsPartialStore(asi))
517 panic("Partial Store ASIs not supported\n");
518 if (AsiIsInterrupt(asi))
519 panic("Interrupt ASIs not supported\n");
520
521 if (AsiIsMmu(asi))
522 goto handleMmuRegAccess;
523 if (AsiIsScratchPad(asi))
524 goto handleScratchRegAccess;
525 if (AsiIsQueue(asi))
526 goto handleQueueRegAccess;
527 if (AsiIsSparcError(asi))
528 goto handleSparcErrorRegAccess;
529
530 if (!AsiIsReal(asi) && !AsiIsNucleus(asi))
531 panic("Accessing ASI %#X. Should we?\n", asi);
532 }
533
534continueDtbFlow:
535 // If the asi is unaligned trap
536 if (vaddr & size-1) {
537 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi);
538 return new MemAddressNotAligned;
539 }
540
541 if (addr_mask)
542 vaddr = vaddr & VAddrAMask;
543
544 if (!validVirtualAddress(vaddr, addr_mask)) {
545 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi);
546 return new DataAccessException;
547 }
548
549
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
550 if ((!lsuDm && !hpriv) || AsiIsReal(asi)) {
559 if ((!lsu_dm && !hpriv) || AsiIsReal(asi)) {
551 real = true;
552 context = 0;
553 };
554
555 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
556 req->setPaddr(req->getVaddr() & PAddrImplMask);
557 return NoFault;
558 }
559
560 e = lookup(req->getVaddr(), part_id, real, context);
561
562 if (e == NULL || !e->valid) {
563 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
564 vaddr & ~BytesInPageMask | context);
565 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
566 if (real)
567 return new DataRealTranslationMiss;
568 else
569 return new FastDataAccessMMUMiss;
570
571 }
572
573
574 if (write && !e->pte.writable()) {
575 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi);
576 return new FastDataAccessProtection;
577 }
578
579 if (e->pte.nofault() && !AsiIsNoFault(asi)) {
580 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi);
581 return new DataAccessException;
582 }
583
584 if (e->pte.sideffect())
585 req->setFlags(req->getFlags() | UNCACHEABLE);
586
587
588 if (!priv && e->pte.priv()) {
589 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
590 return new DataAccessException;
591 }
592
593 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
594 req->getVaddr() & e->pte.size()-1);
595 DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr());
596 return NoFault;
597 /** Normal flow ends here. */
598
599handleScratchRegAccess:
600 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
601 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
602 return new DataAccessException;
603 }
604 goto regAccessOk;
605
606handleQueueRegAccess:
607 if (!priv && !hpriv) {
608 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
609 return new PrivilegedAction;
610 }
611 if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) {
612 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
613 return new DataAccessException;
614 }
615 goto regAccessOk;
616
617handleSparcErrorRegAccess:
618 if (!hpriv) {
619 if (priv) {
620 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
621 return new DataAccessException;
622 } else {
623 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
624 return new PrivilegedAction;
625 }
626 }
627 goto regAccessOk;
628
629
630regAccessOk:
631handleMmuRegAccess:
632 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n");
633 req->setMmapedIpr(true);
634 req->setPaddr(req->getVaddr());
635 return NoFault;
636};
637
638Tick
639DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
640{
641 Addr va = pkt->getAddr();
642 ASI asi = (ASI)pkt->req->getAsi();
560 real = true;
561 context = 0;
562 };
563
564 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
565 req->setPaddr(req->getVaddr() & PAddrImplMask);
566 return NoFault;
567 }
568
569 e = lookup(req->getVaddr(), 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
602 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());
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;
643
644 DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n",
645 (uint32_t)pkt->req->getAsi(), pkt->getAddr());
646
647 switch (asi) {
648 case ASI_LSU_CONTROL_REG:
649 assert(va == 0);
650 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL));
651 break;
652 case ASI_MMU:
653 switch (va) {
654 case 0x8:
655 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT));
656 break;
657 case 0x10:
658 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT));
659 break;
660 default:
661 goto doMmuReadError;
662 }
663 break;
664 case ASI_QUEUE:
665 pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD +
666 (va >> 4) - 0x3c));
667 break;
668 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0:
669 assert(va == 0);
670 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0));
671 break;
672 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1:
673 assert(va == 0);
674 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1));
675 break;
676 case ASI_DMMU_CTXT_ZERO_CONFIG:
677 assert(va == 0);
678 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG));
679 break;
680 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0:
681 assert(va == 0);
682 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0));
683 break;
684 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1:
685 assert(va == 0);
686 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1));
687 break;
688 case ASI_IMMU_CTXT_ZERO_CONFIG:
689 assert(va == 0);
690 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG));
691 break;
692 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0:
693 assert(va == 0);
694 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0));
695 break;
696 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1:
697 assert(va == 0);
698 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1));
699 break;
700 case ASI_DMMU_CTXT_NONZERO_CONFIG:
701 assert(va == 0);
702 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG));
703 break;
704 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0:
705 assert(va == 0);
706 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0));
707 break;
708 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1:
709 assert(va == 0);
710 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1));
711 break;
712 case ASI_IMMU_CTXT_NONZERO_CONFIG:
713 assert(va == 0);
714 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG));
715 break;
716 case ASI_SPARC_ERROR_STATUS_REG:
717 warn("returning 0 for SPARC ERROR regsiter read\n");
718 pkt->set(0);
719 break;
720 case ASI_HYP_SCRATCHPAD:
721 case ASI_SCRATCHPAD:
722 pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3)));
723 break;
724 case ASI_IMMU:
725 switch (va) {
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;
726 case 0x30:
727 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS));
728 break;
729 default:
730 goto doMmuReadError;
731 }
732 break;
733 case ASI_DMMU:
734 switch (va) {
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;
735 case 0x30:
736 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS));
737 break;
738 case 0x80:
739 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID));
740 break;
741 default:
742 goto doMmuReadError;
743 }
744 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);
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
745 default:
746doMmuReadError:
747 panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n",
748 (uint32_t)asi, va);
749 }
750 pkt->result = Packet::Success;
751 return tc->getCpuPtr()->cycles(1);
752}
753
754Tick
755DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
756{
757 uint64_t data = gtoh(pkt->get<uint64_t>());
758 Addr va = pkt->getAddr();
759 ASI asi = (ASI)pkt->req->getAsi();
760
761 Addr ta_insert;
762 Addr va_insert;
763 Addr ct_insert;
764 int part_insert;
765 int entry_insert = -1;
766 bool real_insert;
767 PageTableEntry pte;
768
769 DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n",
770 (uint32_t)asi, va, data);
771
772 switch (asi) {
773 case ASI_LSU_CONTROL_REG:
774 assert(va == 0);
775 tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data);
776 break;
777 case ASI_MMU:
778 switch (va) {
779 case 0x8:
780 tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data);
781 break;
782 case 0x10:
783 tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data);
784 break;
785 default:
786 goto doMmuWriteError;
787 }
788 break;
789 case ASI_QUEUE:
790 assert(mbits(data,13,6) == data);
791 tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD +
792 (va >> 4) - 0x3c, data);
793 break;
794 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0:
795 assert(va == 0);
796 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data);
797 break;
798 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1:
799 assert(va == 0);
800 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data);
801 break;
802 case ASI_DMMU_CTXT_ZERO_CONFIG:
803 assert(va == 0);
804 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data);
805 break;
806 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0:
807 assert(va == 0);
808 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data);
809 break;
810 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1:
811 assert(va == 0);
812 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data);
813 break;
814 case ASI_IMMU_CTXT_ZERO_CONFIG:
815 assert(va == 0);
816 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data);
817 break;
818 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0:
819 assert(va == 0);
820 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data);
821 break;
822 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1:
823 assert(va == 0);
824 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data);
825 break;
826 case ASI_DMMU_CTXT_NONZERO_CONFIG:
827 assert(va == 0);
828 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data);
829 break;
830 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0:
831 assert(va == 0);
832 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data);
833 break;
834 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1:
835 assert(va == 0);
836 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data);
837 break;
838 case ASI_IMMU_CTXT_NONZERO_CONFIG:
839 assert(va == 0);
840 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data);
841 break;
842 case ASI_SPARC_ERROR_EN_REG:
843 case ASI_SPARC_ERROR_STATUS_REG:
844 warn("Ignoring write to SPARC ERROR regsiter\n");
845 break;
846 case ASI_HYP_SCRATCHPAD:
847 case ASI_SCRATCHPAD:
848 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data);
849 break;
850 case ASI_IMMU:
851 switch (va) {
852 case 0x30:
853 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data);
854 break;
855 default:
856 goto doMmuWriteError;
857 }
858 break;
859 case ASI_ITLB_DATA_ACCESS_REG:
860 entry_insert = bits(va, 8,3);
861 case ASI_ITLB_DATA_IN_REG:
862 assert(entry_insert != -1 || mbits(va,10,9) == va);
863 ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
864 va_insert = mbits(ta_insert, 63,13);
865 ct_insert = mbits(ta_insert, 12,0);
866 part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID);
867 real_insert = bits(va, 9,9);
868 pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v :
869 PageTableEntry::sun4u);
870 tc->getITBPtr()->insert(va_insert, part_insert, ct_insert, real_insert,
871 pte, entry_insert);
872 break;
873 case ASI_DTLB_DATA_ACCESS_REG:
874 entry_insert = bits(va, 8,3);
875 case ASI_DTLB_DATA_IN_REG:
876 assert(entry_insert != -1 || mbits(va,10,9) == va);
877 ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
878 va_insert = mbits(ta_insert, 63,13);
879 ct_insert = mbits(ta_insert, 12,0);
880 part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID);
881 real_insert = bits(va, 9,9);
882 pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v :
883 PageTableEntry::sun4u);
884 insert(va_insert, part_insert, ct_insert, real_insert, pte, entry_insert);
885 break;
886 case ASI_DMMU:
887 switch (va) {
888 case 0x30:
889 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data);
890 break;
891 case 0x80:
892 tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data);
893 break;
894 default:
895 goto doMmuWriteError;
896 }
897 break;
898 default:
899doMmuWriteError:
900 panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n",
901 (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data);
902 }
903 pkt->result = Packet::Success;
904 return tc->getCpuPtr()->cycles(1);
905}
906
907void
908TLB::serialize(std::ostream &os)
909{
910 panic("Need to implement serialize tlb for SPARC\n");
911}
912
913void
914TLB::unserialize(Checkpoint *cp, const std::string &section)
915{
916 panic("Need to implement unserialize tlb for SPARC\n");
917}
918
919
920DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB)
921
922BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
923
924 Param<int> size;
925
926END_DECLARE_SIM_OBJECT_PARAMS(ITB)
927
928BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
929
930 INIT_PARAM_DFLT(size, "TLB size", 48)
931
932END_INIT_SIM_OBJECT_PARAMS(ITB)
933
934
935CREATE_SIM_OBJECT(ITB)
936{
937 return new ITB(getInstanceName(), size);
938}
939
940REGISTER_SIM_OBJECT("SparcITB", ITB)
941
942BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
943
944 Param<int> size;
945
946END_DECLARE_SIM_OBJECT_PARAMS(DTB)
947
948BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
949
950 INIT_PARAM_DFLT(size, "TLB size", 64)
951
952END_INIT_SIM_OBJECT_PARAMS(DTB)
953
954
955CREATE_SIM_OBJECT(DTB)
956{
957 return new DTB(getInstanceName(), size);
958}
959
960REGISTER_SIM_OBJECT("SparcDTB", DTB)
961}
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 &section)
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}