summaryrefslogtreecommitdiff
path: root/arch/alpha
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/faults.cc45
-rw-r--r--arch/alpha/faults.hh97
-rw-r--r--arch/alpha/isa/main.isa20
-rw-r--r--arch/alpha/isa/mem.isa6
-rw-r--r--arch/alpha/linux/system.hh1
-rw-r--r--arch/alpha/tlb.cc104
-rw-r--r--arch/alpha/tlb.hh6
7 files changed, 178 insertions, 101 deletions
diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc
index e0918da21..0083aa9f3 100644
--- a/arch/alpha/faults.cc
+++ b/arch/alpha/faults.cc
@@ -30,6 +30,9 @@
#include "cpu/exec_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
+#if FULL_SYSTEM
+#include "arch/alpha/ev5.hh"
+#endif
namespace AlphaISA
{
@@ -70,6 +73,10 @@ FaultName DtbAcvFault::_name = "dfault";
FaultVect DtbAcvFault::_vect = 0x0381;
FaultStat DtbAcvFault::_count;
+FaultName DtbAlignmentFault::_name = "unalign";
+FaultVect DtbAlignmentFault::_vect = 0x0301;
+FaultStat DtbAlignmentFault::_count;
+
FaultName ItbMissFault::_name = "itbmiss";
FaultVect ItbMissFault::_vect = 0x0181;
FaultStat ItbMissFault::_count;
@@ -125,6 +132,44 @@ void ArithmeticFault::invoke(ExecContext * xc)
panic("Arithmetic traps are unimplemented!");
}
+void DtbFault::invoke(ExecContext * xc)
+{
+ // Set fault address and flags. Even though we're modeling an
+ // EV5, we use the EV6 technique of not latching fault registers
+ // on VPTE loads (instead of locking the registers until IPR_VA is
+ // read, like the EV5). The EV6 approach is cleaner and seems to
+ // work with EV5 PAL code, but not the other way around.
+ if (!xc->misspeculating()
+ && !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) {
+ // set VA register with faulting address
+ xc->setMiscReg(AlphaISA::IPR_VA, vaddr);
+
+ // set MM_STAT register flags
+ xc->setMiscReg(AlphaISA::IPR_MM_STAT,
+ (((EV5::Opcode(xc->getInst()) & 0x3f) << 11)
+ | ((EV5::Ra(xc->getInst()) & 0x1f) << 6)
+ | (flags & 0x3f)));
+
+ // set VA_FORM register with faulting formatted address
+ xc->setMiscReg(AlphaISA::IPR_VA_FORM,
+ xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
+ }
+
+ AlphaFault::invoke(xc);
+}
+
+void ItbFault::invoke(ExecContext * xc)
+{
+ if (!xc->misspeculating()) {
+ xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
+ xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
+ xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
+ (AlphaISA::VAddr(pc).vpn() << 3));
+ }
+
+ AlphaFault::invoke(xc);
+}
+
#endif
} // namespace AlphaISA
diff --git a/arch/alpha/faults.hh b/arch/alpha/faults.hh
index 1a196cc94..e8ccc6b79 100644
--- a/arch/alpha/faults.hh
+++ b/arch/alpha/faults.hh
@@ -29,6 +29,7 @@
#ifndef __ALPHA_FAULTS_HH__
#define __ALPHA_FAULTS_HH__
+#include "arch/alpha/isa_traits.hh"
#include "sim/faults.hh"
// The design of the "name" and "vect" functions is in sim/faults.hh
@@ -130,85 +131,167 @@ class InterruptFault : public AlphaFault
FaultStat & countStat() {return _count;}
};
-class NDtbMissFault : public AlphaFault
+class DtbFault : public AlphaFault
+{
+#if FULL_SYSTEM
+ private:
+ AlphaISA::VAddr vaddr;
+ uint32_t reqFlags;
+ uint64_t flags;
+ public:
+ DtbFault(AlphaISA::VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags)
+ : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags)
+ { }
+#endif
+ FaultName name() = 0;
+ FaultVect vect() = 0;
+ FaultStat & countStat() = 0;
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
+class NDtbMissFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+#if FULL_SYSTEM
+ NDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class PDtbMissFault : public AlphaFault
+class PDtbMissFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+#if FULL_SYSTEM
+ PDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class DtbPageFault : public AlphaFault
+class DtbPageFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+#if FULL_SYSTEM
+ DtbPageFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class DtbAcvFault : public AlphaFault
+class DtbAcvFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+#if FULL_SYSTEM
+ DtbAcvFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class ItbMissFault : public AlphaFault
+class DtbAlignmentFault : public DtbFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+#if FULL_SYSTEM
+ DtbAlignmentFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+ : DtbFault(vaddr, reqFlags, flags)
+ { }
+#endif
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbFault : public AlphaFault
+{
+ private:
+ Addr pc;
+ public:
+ ItbFault(Addr _pc)
+ : pc(_pc)
+ { }
+ FaultName name() = 0;
+ FaultVect vect() = 0;
+ FaultStat & countStat() = 0;
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
+class ItbMissFault : public ItbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+ ItbMissFault(Addr pc)
+ : ItbFault(pc)
+ { }
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class ItbPageFault : public AlphaFault
+class ItbPageFault : public ItbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+ ItbPageFault(Addr pc)
+ : ItbFault(pc)
+ { }
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
-class ItbAcvFault : public AlphaFault
+class ItbAcvFault : public ItbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
+ ItbAcvFault(Addr pc)
+ : ItbFault(pc)
+ { }
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa
index d4c744fbc..746fe776d 100644
--- a/arch/alpha/isa/main.isa
+++ b/arch/alpha/isa/main.isa
@@ -418,31 +418,31 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{
}};
// Integer instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/int.isa"
+##include "int.isa"
// Floating-point instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/fp.isa"
+##include "fp.isa"
// Memory instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/mem.isa"
+##include "mem.isa"
// Branch/jump instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/branch.isa"
+##include "branch.isa"
// PAL instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/pal.isa"
+##include "pal.isa"
// Opcdec fault instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/opcdec.isa"
+##include "opcdec.isa"
// Unimplemented instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/unimp.isa"
+##include "unimp.isa"
// Unknown instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/unknown.isa"
+##include "unknown.isa"
// Execution utility functions
-##include "m5/arch/alpha/isa/util.isa"
+##include "util.isa"
// The actual decoder
-##include "m5/arch/alpha/isa/decoder.isa"
+##include "decoder.isa"
diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa
index 3c8b4f755..8742d308f 100644
--- a/arch/alpha/isa/mem.isa
+++ b/arch/alpha/isa/mem.isa
@@ -311,8 +311,7 @@ def template LoadCompleteAcc {{
Fault fault = NoFault;
%(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
+ %(op_decl)s;
memcpy(&Mem, data, sizeof(Mem));
@@ -410,8 +409,7 @@ def template StoreInitiateAcc {{
uint64_t write_result = 0;
%(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
+ %(op_decl)s;
%(op_rd)s;
%(ea_code)s;
diff --git a/arch/alpha/linux/system.hh b/arch/alpha/linux/system.hh
index 035e2a427..0c1fb037e 100644
--- a/arch/alpha/linux/system.hh
+++ b/arch/alpha/linux/system.hh
@@ -39,7 +39,6 @@ class IdleStartEvent;
using namespace AlphaISA;
using namespace Linux;
-using namespace std;
/**
* This class contains linux specific system code (Loading, Events, Binning).
diff --git a/arch/alpha/tlb.cc b/arch/alpha/tlb.cc
index e30a8e595..562235ef8 100644
--- a/arch/alpha/tlb.cc
+++ b/arch/alpha/tlb.cc
@@ -290,17 +290,6 @@ AlphaITB::regStats()
accesses = hits + misses;
}
-void
-AlphaITB::fault(Addr pc, ExecContext *xc) const
-{
- if (!xc->misspeculating()) {
- xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
- xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
- xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
- (AlphaISA::VAddr(pc).vpn() << 3));
- }
-}
-
Fault
AlphaITB::translate(MemReqPtr &req) const
@@ -319,9 +308,8 @@ AlphaITB::translate(MemReqPtr &req) const
} else {
// verify that this is a good virtual address
if (!validVirtualAddress(req->vaddr)) {
- fault(req->vaddr, req->xc);
acv++;
- return new ItbAcvFault;
+ return new ItbAcvFault(req->vaddr);
}
@@ -336,9 +324,8 @@ AlphaITB::translate(MemReqPtr &req) const
// only valid in kernel mode
if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) !=
AlphaISA::mode_kernel) {
- fault(req->vaddr, req->xc);
acv++;
- return new ItbAcvFault;
+ return new ItbAcvFault(req->vaddr);
}
req->paddr = req->vaddr & PAddrImplMask;
@@ -358,9 +345,8 @@ AlphaITB::translate(MemReqPtr &req) const
asn);
if (!pte) {
- fault(req->vaddr, req->xc);
misses++;
- return new ItbPageFault;
+ return new ItbPageFault(req->vaddr);
}
req->paddr = (pte->ppn << AlphaISA::PageShift) +
@@ -370,9 +356,8 @@ AlphaITB::translate(MemReqPtr &req) const
if (!(pte->xre &
(1 << ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM))))) {
// instruction access fault
- fault(req->vaddr, req->xc);
acv++;
- return new ItbAcvFault;
+ return new ItbAcvFault(req->vaddr);
}
hits++;
@@ -465,34 +450,6 @@ AlphaDTB::regStats()
accesses = read_accesses + write_accesses;
}
-void
-AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
-{
- ExecContext *xc = req->xc;
- AlphaISA::VAddr vaddr = req->vaddr;
-
- // Set fault address and flags. Even though we're modeling an
- // EV5, we use the EV6 technique of not latching fault registers
- // on VPTE loads (instead of locking the registers until IPR_VA is
- // read, like the EV5). The EV6 approach is cleaner and seems to
- // work with EV5 PAL code, but not the other way around.
- if (!xc->misspeculating()
- && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
- // set VA register with faulting address
- xc->setMiscReg(AlphaISA::IPR_VA, req->vaddr);
-
- // set MM_STAT register flags
- xc->setMiscReg(AlphaISA::IPR_MM_STAT,
- (((Opcode(xc->getInst()) & 0x3f) << 11)
- | ((Ra(xc->getInst()) & 0x1f) << 6)
- | (flags & 0x3f)));
-
- // set VA_FORM register with faulting formatted address
- xc->setMiscReg(AlphaISA::IPR_VA_FORM,
- xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
- }
-}
-
Fault
AlphaDTB::translate(MemReqPtr &req, bool write) const
{
@@ -507,10 +464,10 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
* Check for alignment faults
*/
if (req->vaddr & (req->size - 1)) {
- fault(req, write ? MM_STAT_WR_MASK : 0);
DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr,
req->size);
- return genAlignmentFault();
+ uint64_t flags = write ? MM_STAT_WR_MASK : 0;
+ return new DtbAlignmentFault(req->vaddr, req->flags, flags);
}
if (pc & 0x1) {
@@ -525,12 +482,11 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
} else {
// verify that this is a good virtual address
if (!validVirtualAddress(req->vaddr)) {
- fault(req, (write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_BAD_VA_MASK |
- MM_STAT_ACV_MASK);
-
if (write) { write_acv++; } else { read_acv++; }
- return new DtbPageFault;
+ uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_BAD_VA_MASK |
+ MM_STAT_ACV_MASK;
+ return new DtbPageFault(req->vaddr, req->flags, flags);
}
// Check for "superpage" mapping
@@ -544,10 +500,10 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
// only valid in kernel mode
if (DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)) !=
AlphaISA::mode_kernel) {
- fault(req, ((write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_ACV_MASK));
if (write) { write_acv++; } else { read_acv++; }
- return new DtbAcvFault;
+ uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_ACV_MASK);
+ return new DtbAcvFault(req->vaddr, req->flags, flags);
}
req->paddr = req->vaddr & PAddrImplMask;
@@ -574,12 +530,14 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
if (!pte) {
// page fault
- fault(req, (write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_DTB_MISS_MASK);
if (write) { write_misses++; } else { read_misses++; }
+ uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_DTB_MISS_MASK;
return (req->flags & VPTE) ?
- (Fault)(new PDtbMissFault) :
- (Fault)(new NDtbMissFault);
+ (Fault)(new PDtbMissFault(req->vaddr, req->flags,
+ flags)) :
+ (Fault)(new NDtbMissFault(req->vaddr, req->flags,
+ flags));
}
req->paddr = (pte->ppn << AlphaISA::PageShift) +
@@ -588,29 +546,29 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
if (write) {
if (!(pte->xwe & MODE2MASK(mode))) {
// declare the instruction access fault
- fault(req, MM_STAT_WR_MASK |
- MM_STAT_ACV_MASK |
- (pte->fonw ? MM_STAT_FONW_MASK : 0));
write_acv++;
- return new DtbPageFault;
+ uint64_t flags = MM_STAT_WR_MASK |
+ MM_STAT_ACV_MASK |
+ (pte->fonw ? MM_STAT_FONW_MASK : 0);
+ return new DtbPageFault(req->vaddr, req->flags, flags);
}
if (pte->fonw) {
- fault(req, MM_STAT_WR_MASK |
- MM_STAT_FONW_MASK);
write_acv++;
- return new DtbPageFault;
+ uint64_t flags = MM_STAT_WR_MASK |
+ MM_STAT_FONW_MASK;
+ return new DtbPageFault(req->vaddr, req->flags, flags);
}
} else {
if (!(pte->xre & MODE2MASK(mode))) {
- fault(req, MM_STAT_ACV_MASK |
- (pte->fonr ? MM_STAT_FONR_MASK : 0));
read_acv++;
- return new DtbAcvFault;
+ uint64_t flags = MM_STAT_ACV_MASK |
+ (pte->fonr ? MM_STAT_FONR_MASK : 0);
+ return new DtbAcvFault(req->vaddr, req->flags, flags);
}
if (pte->fonr) {
- fault(req, MM_STAT_FONR_MASK);
read_acv++;
- return new DtbPageFault;
+ uint64_t flags = MM_STAT_FONR_MASK;
+ return new DtbPageFault(req->vaddr, req->flags, flags);
}
}
}
diff --git a/arch/alpha/tlb.hh b/arch/alpha/tlb.hh
index 1c299e8b9..676345f01 100644
--- a/arch/alpha/tlb.hh
+++ b/arch/alpha/tlb.hh
@@ -88,9 +88,6 @@ class AlphaITB : public AlphaTLB
mutable Stats::Scalar<> acv;
mutable Stats::Formula accesses;
- protected:
- void fault(Addr pc, ExecContext *xc) const;
-
public:
AlphaITB(const std::string &name, int size);
virtual void regStats();
@@ -114,9 +111,6 @@ class AlphaDTB : public AlphaTLB
Stats::Formula acv;
Stats::Formula accesses;
- protected:
- void fault(MemReqPtr &req, uint64_t flags) const;
-
public:
AlphaDTB(const std::string &name, int size);
virtual void regStats();