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