2 * Copyright (c) 2001-2004 The Regents of The University of Michigan
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.
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.
33 #include "base/inifile.hh"
34 #include "base/str.hh"
35 #include "base/trace.hh"
36 #include "cpu/exec_context.hh"
37 #include "sim/builder.hh"
38 #include "targetarch/alpha_memory.hh"
39 #include "targetarch/ev5.hh"
43 ///////////////////////////////////////////////////////////////////////
48 bool uncacheBit39
= false;
49 bool uncacheBit40
= false;
52 AlphaTLB::AlphaTLB(const string
&name
, int s
)
53 : SimObject(name
), size(s
), nlu(0)
55 table
= new AlphaISA::PTE
[size
];
56 memset(table
, 0, sizeof(AlphaISA::PTE
[size
]));
65 // look up an entry in the TLB
67 AlphaTLB::lookup(Addr vpn
, uint8_t asn
) const
69 DPRINTF(TLB
, "lookup %#x, asn %#x\n", vpn
, (int)asn
);
71 PageTable::const_iterator i
= lookupTable
.find(vpn
);
72 if (i
== lookupTable
.end())
75 while (i
->first
== vpn
) {
76 int index
= i
->second
;
77 AlphaISA::PTE
*pte
= &table
[index
];
79 if (vpn
== pte
->tag
&& (pte
->asma
|| pte
->asn
== asn
))
91 AlphaTLB::checkCacheability(MemReqPtr
&req
)
93 // in Alpha, cacheability is controlled by upper-level bits of the
97 * We support having the uncacheable bit in either bit 39 or bit 40.
98 * The Turbolaser platform (and EV5) support having the bit in 39, but
99 * Tsunami (which Linux assumes uses an EV6) generates accesses with
100 * the bit in 40. So we must check for both, but we have debug flags
101 * to catch a weird case where both are used, which shouldn't happen.
106 if (req
->paddr
& PA_UNCACHED_BIT_39
) {
108 if (req
->paddr
& PA_UNCACHED_BIT_43
) {
110 // IPR memory space not implemented
111 if (PA_IPR_SPACE(req
->paddr
)) {
112 if (!req
->xc
->misspeculating()) {
113 switch (req
->paddr
) {
114 case ULL(0xFFFFF00188):
119 panic("IPR memory space not implemented! PA=%x\n",
124 // mark request as uncacheable
125 req
->flags
|= UNCACHEABLE
;
128 // Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
129 req
->paddr
&= PA_UNCACHED_MASK
;
136 // insert a new TLB entry
138 AlphaTLB::insert(Addr vaddr
, AlphaISA::PTE
&pte
)
140 if (table
[nlu
].valid
) {
141 Addr oldvpn
= table
[nlu
].tag
;
142 PageTable::iterator i
= lookupTable
.find(oldvpn
);
144 if (i
== lookupTable
.end())
145 panic("TLB entry not found in lookupTable");
148 while ((index
= i
->second
) != nlu
) {
149 if (table
[index
].tag
!= oldvpn
)
150 panic("TLB entry not found in lookupTable");
155 DPRINTF(TLB
, "remove @%d: %#x -> %#x\n", nlu
, oldvpn
, table
[nlu
].ppn
);
157 lookupTable
.erase(i
);
160 Addr vpn
= VA_VPN(vaddr
);
161 DPRINTF(TLB
, "insert @%d: %#x -> %#x\n", nlu
, vpn
, pte
.ppn
);
164 table
[nlu
].tag
= vpn
;
165 table
[nlu
].valid
= true;
167 lookupTable
.insert(make_pair(vpn
, nlu
));
174 memset(table
, 0, sizeof(AlphaISA::PTE
[size
]));
180 AlphaTLB::flushProcesses()
182 PageTable::iterator i
= lookupTable
.begin();
183 PageTable::iterator end
= lookupTable
.end();
185 int index
= i
->second
;
186 AlphaISA::PTE
*pte
= &table
[index
];
190 DPRINTF(TLB
, "flush @%d: %#x -> %#x\n", index
, pte
->tag
, pte
->ppn
);
192 lookupTable
.erase(i
);
200 AlphaTLB::flushAddr(Addr vaddr
, uint8_t asn
)
202 Addr vpn
= VA_VPN(vaddr
);
204 PageTable::iterator i
= lookupTable
.find(vpn
);
205 if (i
== lookupTable
.end())
208 while (i
->first
== vpn
) {
209 int index
= i
->second
;
210 AlphaISA::PTE
*pte
= &table
[index
];
213 if (vpn
== pte
->tag
&& (pte
->asma
|| pte
->asn
== asn
)) {
214 DPRINTF(TLB
, "flushaddr @%d: %#x -> %#x\n", index
, vpn
, pte
->ppn
);
216 // invalidate this entry
219 lookupTable
.erase(i
);
228 AlphaTLB::serialize(ostream
&os
)
230 SERIALIZE_SCALAR(size
);
231 SERIALIZE_SCALAR(nlu
);
233 for (int i
= 0; i
< size
; i
++) {
234 nameOut(os
, csprintf("%s.PTE%d", name(), i
));
235 table
[i
].serialize(os
);
240 AlphaTLB::unserialize(Checkpoint
*cp
, const string
§ion
)
242 UNSERIALIZE_SCALAR(size
);
243 UNSERIALIZE_SCALAR(nlu
);
245 for (int i
= 0; i
< size
; i
++) {
246 table
[i
].unserialize(cp
, csprintf("%s.PTE%d", section
, i
));
247 if (table
[i
].valid
) {
248 lookupTable
.insert(make_pair(table
[i
].tag
, i
));
254 ///////////////////////////////////////////////////////////////////////
258 AlphaITB::AlphaITB(const std::string
&name
, int size
)
259 : AlphaTLB(name
, size
)
267 .name(name() + ".hits")
270 .name(name() + ".misses")
273 .name(name() + ".acv")
276 .name(name() + ".accesses")
277 .desc("ITB accesses");
279 accesses
= hits
+ misses
;
283 AlphaITB::fault(Addr pc
, ExecContext
*xc
) const
285 uint64_t *ipr
= xc
->regs
.ipr
;
287 if (!xc
->misspeculating()) {
288 ipr
[AlphaISA::IPR_ITB_TAG
] = pc
;
289 ipr
[AlphaISA::IPR_IFAULT_VA_FORM
] =
290 ipr
[AlphaISA::IPR_IVPTBR
] | (VA_VPN(pc
) << 3);
296 AlphaITB::translate(MemReqPtr
&req
) const
298 InternalProcReg
*ipr
= req
->xc
->regs
.ipr
;
300 if (PC_PAL(req
->vaddr
)) {
301 // strip off PAL PC marker (lsb is 1)
302 req
->paddr
= (req
->vaddr
& ~3) & PA_IMPL_MASK
;
307 if (req
->flags
& PHYSICAL
) {
308 req
->paddr
= req
->vaddr
;
310 // verify that this is a good virtual address
311 if (!validVirtualAddress(req
->vaddr
)) {
312 fault(req
->vaddr
, req
->xc
);
314 return ITB_Acv_Fault
;
318 // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
319 // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
321 if ((MCSR_SP(ipr
[AlphaISA::IPR_MCSR
]) & 2) &&
322 VA_SPACE_EV5(req
->vaddr
) == 2) {
324 if (VA_SPACE_EV6(req
->vaddr
) == 0x7e) {
328 // only valid in kernel mode
329 if (ICM_CM(ipr
[AlphaISA::IPR_ICM
]) != AlphaISA::mode_kernel
) {
330 fault(req
->vaddr
, req
->xc
);
332 return ITB_Acv_Fault
;
335 req
->paddr
= req
->vaddr
& PA_IMPL_MASK
;
338 // sign extend the physical address properly
339 if (req
->paddr
& PA_UNCACHED_BIT_40
)
340 req
->paddr
|= ULL(0xf0000000000);
342 req
->paddr
&= ULL(0xffffffffff);
346 // not a physical address: need to look up pte
347 AlphaISA::PTE
*pte
= lookup(VA_VPN(req
->vaddr
),
348 DTB_ASN_ASN(ipr
[AlphaISA::IPR_DTB_ASN
]));
351 fault(req
->vaddr
, req
->xc
);
353 return ITB_Fault_Fault
;
356 req
->paddr
= PA_PFN2PA(pte
->ppn
) + VA_POFS(req
->vaddr
& ~3);
358 // check permissions for this access
359 if (!(pte
->xre
& (1 << ICM_CM(ipr
[AlphaISA::IPR_ICM
])))) {
360 // instruction access fault
361 fault(req
->vaddr
, req
->xc
);
363 return ITB_Acv_Fault
;
370 // check that the physical address is ok (catch bad physical addresses)
371 if (req
->paddr
& ~PA_IMPL_MASK
)
372 return Machine_Check_Fault
;
374 checkCacheability(req
);
379 ///////////////////////////////////////////////////////////////////////
383 AlphaDTB::AlphaDTB(const std::string
&name
, int size
)
384 : AlphaTLB(name
, size
)
391 .name(name() + ".read_hits")
392 .desc("DTB read hits")
396 .name(name() + ".read_misses")
397 .desc("DTB read misses")
401 .name(name() + ".read_acv")
402 .desc("DTB read access violations")
406 .name(name() + ".read_accesses")
407 .desc("DTB read accesses")
411 .name(name() + ".write_hits")
412 .desc("DTB write hits")
416 .name(name() + ".write_misses")
417 .desc("DTB write misses")
421 .name(name() + ".write_acv")
422 .desc("DTB write access violations")
426 .name(name() + ".write_accesses")
427 .desc("DTB write accesses")
431 .name(name() + ".hits")
436 .name(name() + ".misses")
441 .name(name() + ".acv")
442 .desc("DTB access violations")
446 .name(name() + ".accesses")
447 .desc("DTB accesses")
450 hits
= read_hits
+ write_hits
;
451 misses
= read_misses
+ write_misses
;
452 acv
= read_acv
+ write_acv
;
453 accesses
= read_accesses
+ write_accesses
;
457 AlphaDTB::fault(MemReqPtr
&req
, uint64_t flags
) const
459 ExecContext
*xc
= req
->xc
;
460 Addr vaddr
= req
->vaddr
;
461 uint64_t *ipr
= xc
->regs
.ipr
;
463 // Set fault address and flags. Even though we're modeling an
464 // EV5, we use the EV6 technique of not latching fault registers
465 // on VPTE loads (instead of locking the registers until IPR_VA is
466 // read, like the EV5). The EV6 approach is cleaner and seems to
467 // work with EV5 PAL code, but not the other way around.
468 if (!xc
->misspeculating()
469 && !(req
->flags
& VPTE
) && !(req
->flags
& NO_FAULT
)) {
470 // set VA register with faulting address
471 ipr
[AlphaISA::IPR_VA
] = vaddr
;
473 // set MM_STAT register flags
474 ipr
[AlphaISA::IPR_MM_STAT
] = (((OPCODE(xc
->getInst()) & 0x3f) << 11)
475 | ((RA(xc
->getInst()) & 0x1f) << 6)
478 // set VA_FORM register with faulting formatted address
479 ipr
[AlphaISA::IPR_VA_FORM
] =
480 ipr
[AlphaISA::IPR_MVPTBR
] | (VA_VPN(vaddr
) << 3);
485 AlphaDTB::translate(MemReqPtr
&req
, bool write
) const
487 RegFile
*regs
= &req
->xc
->regs
;
489 InternalProcReg
*ipr
= regs
->ipr
;
491 AlphaISA::mode_type mode
=
492 (AlphaISA::mode_type
)DTB_CM_CM(ipr
[AlphaISA::IPR_DTB_CM
]);
495 mode
= (req
->flags
& ALTMODE
) ?
496 (AlphaISA::mode_type
)ALT_MODE_AM(ipr
[AlphaISA::IPR_ALT_MODE
])
497 : AlphaISA::mode_kernel
;
500 if (req
->flags
& PHYSICAL
) {
501 req
->paddr
= req
->vaddr
;
503 // verify that this is a good virtual address
504 if (!validVirtualAddress(req
->vaddr
)) {
505 fault(req
, ((write
? MM_STAT_WR_MASK
: 0) | MM_STAT_BAD_VA_MASK
|
508 if (write
) { write_acv
++; } else { read_acv
++; }
509 return DTB_Fault_Fault
;
512 // Check for "superpage" mapping
514 if ((MCSR_SP(ipr
[AlphaISA::IPR_MCSR
]) & 2) &&
515 VA_SPACE_EV5(req
->vaddr
) == 2) {
517 if (VA_SPACE_EV6(req
->vaddr
) == 0x7e) {
520 // only valid in kernel mode
521 if (DTB_CM_CM(ipr
[AlphaISA::IPR_DTB_CM
]) !=
522 AlphaISA::mode_kernel
) {
523 fault(req
, ((write
? MM_STAT_WR_MASK
: 0) | MM_STAT_ACV_MASK
));
524 if (write
) { write_acv
++; } else { read_acv
++; }
525 return DTB_Acv_Fault
;
528 req
->paddr
= req
->vaddr
& PA_IMPL_MASK
;
531 // sign extend the physical address properly
532 if (req
->paddr
& PA_UNCACHED_BIT_40
)
533 req
->paddr
|= ULL(0xf0000000000);
535 req
->paddr
&= ULL(0xffffffffff);
544 // not a physical address: need to look up pte
545 AlphaISA::PTE
*pte
= lookup(VA_VPN(req
->vaddr
),
546 DTB_ASN_ASN(ipr
[AlphaISA::IPR_DTB_ASN
]));
551 (write
? MM_STAT_WR_MASK
: 0) | MM_STAT_DTB_MISS_MASK
);
552 if (write
) { write_misses
++; } else { read_misses
++; }
553 return (req
->flags
& VPTE
) ? Pdtb_Miss_Fault
: Ndtb_Miss_Fault
;
556 req
->paddr
= PA_PFN2PA(pte
->ppn
) | VA_POFS(req
->vaddr
);
559 if (!(pte
->xwe
& MODE2MASK(mode
))) {
560 // declare the instruction access fault
561 fault(req
, (MM_STAT_WR_MASK
| MM_STAT_ACV_MASK
|
562 (pte
->fonw
? MM_STAT_FONW_MASK
: 0)));
564 return DTB_Fault_Fault
;
567 fault(req
, MM_STAT_WR_MASK
| MM_STAT_FONW_MASK
);
569 return DTB_Fault_Fault
;
572 if (!(pte
->xre
& MODE2MASK(mode
))) {
573 fault(req
, (MM_STAT_ACV_MASK
|
574 (pte
->fonr
? MM_STAT_FONR_MASK
: 0)));
576 return DTB_Acv_Fault
;
579 fault(req
, MM_STAT_FONR_MASK
);
581 return DTB_Fault_Fault
;
592 // check that the physical address is ok (catch bad physical addresses)
593 if (req
->paddr
& ~PA_IMPL_MASK
)
594 return Machine_Check_Fault
;
596 checkCacheability(req
);
602 AlphaTLB::index(bool advance
)
604 AlphaISA::PTE
*pte
= &table
[nlu
];
612 DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB
)
614 BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB
)
618 END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB
)
620 BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB
)
622 INIT_PARAM_DFLT(size
, "TLB size", 48)
624 END_INIT_SIM_OBJECT_PARAMS(AlphaITB
)
627 CREATE_SIM_OBJECT(AlphaITB
)
629 return new AlphaITB(getInstanceName(), size
);
632 REGISTER_SIM_OBJECT("AlphaITB", AlphaITB
)
634 BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB
)
638 END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB
)
640 BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB
)
642 INIT_PARAM_DFLT(size
, "TLB size", 64)
644 END_INIT_SIM_OBJECT_PARAMS(AlphaDTB
)
647 CREATE_SIM_OBJECT(AlphaDTB
)
649 return new AlphaDTB(getInstanceName(), size
);
652 REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB
)