tlb.cc (3824:8900576818d7) tlb.cc (3825:9b5e6c4d3ecb)
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)
75{
76
77
78 MapIter i;
79 TlbEntry *new_entry;
80
81 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x, pid=%d cid=%d r=%d\n",
82 va, partition_id, context_id, (int)real);
83
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;
89 }
90 }
91
92 // Update the last ently if their all locked
93 if (x == -1)
94 x = 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 }
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;
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
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;
288 tc->setMiscReg(reg, sfsr);
289}
290
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
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);
308 tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a);
309}
310
311
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());
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)
75{
76
77
78 MapIter i;
79 TlbEntry *new_entry;
80
81 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x, pid=%d cid=%d r=%d\n",
82 va, partition_id, context_id, (int)real);
83
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;
89 }
90 }
91
92 // Update the last ently if their all locked
93 if (x == -1)
94 x = 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 }
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;
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
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;
288 tc->setMiscReg(reg, sfsr);
289}
290
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
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);
308 tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a);
309}
310
311
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);
331
332 assert(req->getAsi() == ASI_IMPLICIT);
333
334 if (tl > 0) {
335 asi = ASI_N;
336 ct = Nucleus;
337 context = 0;
338 } else {
339 asi = ASI_P;
340 ct = Primary;
341 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
342 }
343
344 if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) {
345 req->setPaddr(req->getVaddr() & PAddrImplMask);
346 return NoFault;
347 }
348
349 // If the asi is unaligned trap
350 if (vaddr & 0x7) {
351 writeSfsr(tc, false, ct, false, OtherFault, asi);
352 return new MemAddressNotAligned;
353 }
354
355 if (addr_mask)
356 vaddr = vaddr & VAddrAMask;
357
358 if (!validVirtualAddress(vaddr, addr_mask)) {
359 writeSfsr(tc, false, ct, false, VaOutOfRange, asi);
360 return new InstructionAccessException;
361 }
362
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
352 if (vaddr & 0x7) {
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
363 if (lsuIm) {
365 if (!lsuIm) {
364 e = lookup(req->getVaddr(), part_id, true);
365 real = true;
366 context = 0;
367 } else {
368 e = lookup(vaddr, part_id, false, context);
369 }
370
371 if (e == NULL || !e->valid) {
372 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS,
373 vaddr & ~BytesInPageMask | context);
374 if (real)
375 return new InstructionRealTranslationMiss;
376 else
377 return new FastInstructionAccessMMUMiss;
378 }
379
380 // were not priviledged accesing priv page
381 if (!priv && e->pte.priv()) {
382 writeSfsr(tc, false, ct, false, PrivViolation, asi);
383 return new InstructionAccessException;
384 }
385
386 req->setPaddr(e->pte.paddr() & ~e->pte.size() |
387 req->getVaddr() & e->pte.size());
388 return NoFault;
389}
390
391
392
393Fault
394DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
395{
396 /* @todo this could really use some profiling and fixing to make it faster! */
397 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
398 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
399 bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1;
400 uint64_t tl = tc->readMiscReg(MISCREG_TL);
401 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
402 bool hpriv = hpstate >> 2 & 0x1;
403 bool red = hpstate >> 5 >> 0x1;
404 bool addr_mask = pstate >> 3 & 0x1;
405 bool priv = pstate >> 2 & 0x1;
406 bool implicit = false;
407 bool real = false;
408 Addr vaddr = req->getVaddr();
409 Addr size = req->getSize();
410 ContextType ct;
411 int context;
412 ASI asi;
413
414 TlbEntry *e;
415
416 asi = (ASI)req->getAsi();
417 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
418 vaddr, size, asi);
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
388 req->setPaddr(e->pte.paddr() & ~e->pte.size() |
389 req->getVaddr() & e->pte.size());
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);
419
421 DPRINTF(TLB, "TLB: pstate: %#X hpstate: %#X lsudm: %#X part_id: %#X\n",
422 pstate, hpstate, lsuDm, part_id);
420 if (asi == ASI_IMPLICIT)
421 implicit = true;
422
423 if (implicit) {
424 if (tl > 0) {
425 asi = ASI_N;
426 ct = Nucleus;
427 context = 0;
428 } else {
429 asi = ASI_P;
430 ct = Primary;
431 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
432 }
433 } else if (!hpriv && !red) {
434 if (tl > 0 || AsiIsNucleus(asi)) {
435 ct = Nucleus;
436 context = 0;
437 } else if (AsiIsSecondary(asi)) {
438 ct = Secondary;
439 context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT);
440 } else {
441 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
442 ct = Primary; //???
443 }
444
445 // We need to check for priv level/asi priv
446 if (!priv && !AsiIsUnPriv(asi)) {
447 // It appears that context should be Nucleus in these cases?
448 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
449 return new PrivilegedAction;
450 }
451 if (priv && AsiIsHPriv(asi)) {
452 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
453 return new DataAccessException;
454 }
455
456 }
457
458 // If the asi is unaligned trap
459 if (vaddr & size-1) {
460 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi);
461 return new MemAddressNotAligned;
462 }
463
464 if (addr_mask)
465 vaddr = vaddr & VAddrAMask;
466
467 if (!validVirtualAddress(vaddr, addr_mask)) {
468 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi);
469 return new DataAccessException;
470 }
471
472 if (!implicit) {
473 if (AsiIsLittle(asi))
474 panic("Little Endian ASIs not supported\n");
475 if (AsiIsBlock(asi))
476 panic("Block ASIs not supported\n");
477 if (AsiIsNoFault(asi))
478 panic("No Fault ASIs not supported\n");
479 if (AsiIsTwin(asi))
480 panic("Twin ASIs not supported\n");
481 if (AsiIsPartialStore(asi))
482 panic("Partial Store ASIs not supported\n");
483 if (AsiIsInterrupt(asi))
484 panic("Interrupt ASIs not supported\n");
485
486 if (AsiIsMmu(asi))
487 goto handleMmuRegAccess;
488 if (AsiIsScratchPad(asi))
489 goto handleScratchRegAccess;
490 if (AsiIsQueue(asi))
491 goto handleQueueRegAccess;
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
459 }
460
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;
492
493 if (!AsiIsReal(asi) && !AsiIsNucleus(asi))
494 panic("Accessing ASI %#X. Should we?\n", asi);
495 }
496
497 if ((!lsuDm && !hpriv) || AsiIsReal(asi)) {
498 real = true;
499 context = 0;
500 };
501
502 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
503 req->setPaddr(req->getVaddr() & PAddrImplMask);
504 return NoFault;
505 }
506
507 e = lookup(req->getVaddr(), part_id, real, context);
508
509 if (e == NULL || !e->valid) {
510 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
511 vaddr & ~BytesInPageMask | context);
512 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
513 if (real)
514 return new DataRealTranslationMiss;
515 else
516 return new FastDataAccessMMUMiss;
517
518 }
519
520
521 if (write && !e->pte.writable()) {
522 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi);
523 return new FastDataAccessProtection;
524 }
525
526 if (e->pte.nofault() && !AsiIsNoFault(asi)) {
527 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi);
528 return new DataAccessException;
529 }
530
531 if (e->pte.sideffect())
532 req->setFlags(req->getFlags() | UNCACHEABLE);
533
534
535 if (!priv && e->pte.priv()) {
536 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
537 return new DataAccessException;
538 }
539
540 req->setPaddr(e->pte.paddr() & ~e->pte.size() |
541 req->getVaddr() & e->pte.size());
542 return NoFault;
543 /** Normal flow ends here. */
544
545handleScratchRegAccess:
546 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
547 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
548 return new DataAccessException;
549 }
550 goto regAccessOk;
551
552handleQueueRegAccess:
553 if (!priv && !hpriv) {
554 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
555 return new PrivilegedAction;
556 }
557 if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) {
558 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
559 return new DataAccessException;
560 }
561 goto regAccessOk;
562
497
498 if (!AsiIsReal(asi) && !AsiIsNucleus(asi))
499 panic("Accessing ASI %#X. Should we?\n", asi);
500 }
501
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
545 req->setPaddr(e->pte.paddr() & ~e->pte.size() |
546 req->getVaddr() & e->pte.size());
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
563regAccessOk:
564handleMmuRegAccess:
565 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n");
566 req->setMmapedIpr(true);
567 req->setPaddr(req->getVaddr());
568 return NoFault;
569};
570
571Tick
572DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
573{
574 Addr va = pkt->getAddr();
575 ASI asi = (ASI)pkt->req->getAsi();
576
577 DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n",
578 (uint32_t)pkt->req->getAsi(), pkt->getAddr());
579
580 switch (asi) {
581 case ASI_LSU_CONTROL_REG:
582 assert(va == 0);
583 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL));
584 break;
585 case ASI_MMU:
586 switch (va) {
587 case 0x8:
588 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT));
589 break;
590 case 0x10:
591 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT));
592 break;
593 default:
594 goto doMmuReadError;
595 }
596 break;
597 case ASI_QUEUE:
598 pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD +
599 (va >> 4) - 0x3c));
600 break;
601 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0:
602 assert(va == 0);
603 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0));
604 break;
605 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1:
606 assert(va == 0);
607 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1));
608 break;
609 case ASI_DMMU_CTXT_ZERO_CONFIG:
610 assert(va == 0);
611 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG));
612 break;
613 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0:
614 assert(va == 0);
615 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0));
616 break;
617 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1:
618 assert(va == 0);
619 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1));
620 break;
621 case ASI_IMMU_CTXT_ZERO_CONFIG:
622 assert(va == 0);
623 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG));
624 break;
625 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0:
626 assert(va == 0);
627 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0));
628 break;
629 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1:
630 assert(va == 0);
631 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1));
632 break;
633 case ASI_DMMU_CTXT_NONZERO_CONFIG:
634 assert(va == 0);
635 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG));
636 break;
637 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0:
638 assert(va == 0);
639 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0));
640 break;
641 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1:
642 assert(va == 0);
643 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1));
644 break;
645 case ASI_IMMU_CTXT_NONZERO_CONFIG:
646 assert(va == 0);
647 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG));
648 break;
649 case ASI_HYP_SCRATCHPAD:
650 case ASI_SCRATCHPAD:
651 pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3)));
652 break;
653 case ASI_DMMU:
654 switch (va) {
655 case 0x80:
656 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID));
657 break;
658 default:
659 goto doMmuReadError;
660 }
661 break;
662 default:
663doMmuReadError:
664 panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n",
665 (uint32_t)asi, va);
666 }
667 pkt->result = Packet::Success;
668 return tc->getCpuPtr()->cycles(1);
669}
670
671Tick
672DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
673{
674 uint64_t data = gtoh(pkt->get<uint64_t>());
675 Addr va = pkt->getAddr();
676 ASI asi = (ASI)pkt->req->getAsi();
677
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;
667 case ASI_HYP_SCRATCHPAD:
668 case ASI_SCRATCHPAD:
669 pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3)));
670 break;
671 case ASI_DMMU:
672 switch (va) {
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
678 DPRINTF(IPR, "Memory Mapped IPR Write: asi=#%X a=%#x d=%#X\n",
696 DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n",
679 (uint32_t)asi, va, data);
680
681 switch (asi) {
682 case ASI_LSU_CONTROL_REG:
683 assert(va == 0);
684 tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data);
685 break;
686 case ASI_MMU:
687 switch (va) {
688 case 0x8:
689 tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data);
690 break;
691 case 0x10:
692 tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data);
693 break;
694 default:
695 goto doMmuWriteError;
696 }
697 break;
698 case ASI_QUEUE:
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:
699 assert(mbits(va,13,6) == va);
717 assert(mbits(data,13,6) == data);
700 tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD +
701 (va >> 4) - 0x3c, data);
702 break;
703 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0:
704 assert(va == 0);
705 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data);
706 break;
707 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1:
708 assert(va == 0);
709 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data);
710 break;
711 case ASI_DMMU_CTXT_ZERO_CONFIG:
712 assert(va == 0);
713 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data);
714 break;
715 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0:
716 assert(va == 0);
717 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data);
718 break;
719 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1:
720 assert(va == 0);
721 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data);
722 break;
723 case ASI_IMMU_CTXT_ZERO_CONFIG:
724 assert(va == 0);
725 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data);
726 break;
727 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0:
728 assert(va == 0);
729 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data);
730 break;
731 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1:
732 assert(va == 0);
733 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data);
734 break;
735 case ASI_DMMU_CTXT_NONZERO_CONFIG:
736 assert(va == 0);
737 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data);
738 break;
739 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0:
740 assert(va == 0);
741 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data);
742 break;
743 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1:
744 assert(va == 0);
745 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data);
746 break;
747 case ASI_IMMU_CTXT_NONZERO_CONFIG:
748 assert(va == 0);
749 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data);
750 break;
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;
751 case ASI_HYP_SCRATCHPAD:
752 case ASI_SCRATCHPAD:
753 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data);
754 break;
755 case ASI_DMMU:
756 switch (va) {
757 case 0x80:
758 tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data);
759 break;
760 default:
761 goto doMmuWriteError;
762 }
763 break;
764 default:
765doMmuWriteError:
766 panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n",
767 (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data);
768 }
769 pkt->result = Packet::Success;
770 return tc->getCpuPtr()->cycles(1);
771}
772
773void
774TLB::serialize(std::ostream &os)
775{
776 panic("Need to implement serialize tlb for SPARC\n");
777}
778
779void
780TLB::unserialize(Checkpoint *cp, const std::string &section)
781{
782 panic("Need to implement unserialize tlb for SPARC\n");
783}
784
785
786DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB)
787
788BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
789
790 Param<int> size;
791
792END_DECLARE_SIM_OBJECT_PARAMS(ITB)
793
794BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
795
796 INIT_PARAM_DFLT(size, "TLB size", 48)
797
798END_INIT_SIM_OBJECT_PARAMS(ITB)
799
800
801CREATE_SIM_OBJECT(ITB)
802{
803 return new ITB(getInstanceName(), size);
804}
805
806REGISTER_SIM_OBJECT("SparcITB", ITB)
807
808BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
809
810 Param<int> size;
811
812END_DECLARE_SIM_OBJECT_PARAMS(DTB)
813
814BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
815
816 INIT_PARAM_DFLT(size, "TLB size", 64)
817
818END_INIT_SIM_OBJECT_PARAMS(DTB)
819
820
821CREATE_SIM_OBJECT(DTB)
822{
823 return new DTB(getInstanceName(), size);
824}
825
826REGISTER_SIM_OBJECT("SparcDTB", DTB)
827}
773 case ASI_HYP_SCRATCHPAD:
774 case ASI_SCRATCHPAD:
775 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data);
776 break;
777 case ASI_DMMU:
778 switch (va) {
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}