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..fa826fe78 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 ItbPageFault : public AlphaFault +class ItbFault : public AlphaFault +{ + private: + Addr pc; + public: + ItbFault(Addr _pc) + : pc(_pc) + { } + FaultName name() { panic("Dtb Fault is a base class"); } + FaultVect vect() { panic("Dtb Fault is a base class"); } + FaultStat & countStat() { panic("Dtb Fault is a base class"); } +#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 ItbAcvFault : 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 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/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();