diff options
Diffstat (limited to 'arch/alpha')
-rw-r--r-- | arch/alpha/alpha_memory.cc | 47 | ||||
-rw-r--r-- | arch/alpha/alpha_memory.hh | 2 | ||||
-rw-r--r-- | arch/alpha/ev5.cc | 5 | ||||
-rw-r--r-- | arch/alpha/isa_desc | 11 | ||||
-rw-r--r-- | arch/alpha/isa_traits.hh | 1 |
5 files changed, 29 insertions, 37 deletions
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index d7004b461..f8be89cbe 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -430,12 +430,19 @@ AlphaDTB::regStats() } void -AlphaDTB::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const +AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const { + ExecContext *xc = req->xc; + Addr vaddr = req->vaddr; uint64_t *ipr = xc->regs.ipr; - // set fault address and flags - if (!xc->misspeculating() && !xc->regs.intrlock) { + // 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 ipr[AlphaISA::IPR_VA] = vaddr; @@ -447,9 +454,6 @@ AlphaDTB::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const // set VA_FORM register with faulting formatted address ipr[AlphaISA::IPR_VA_FORM] = ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3); - - // lock these registers until the VA register is read - xc->regs.intrlock = true; } } @@ -474,10 +478,8 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const } else { // verify that this is a good virtual address if (!validVirtualAddress(req->vaddr)) { - fault(req->vaddr, - ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK | - MM_STAT_ACV_MASK), - req->xc); + 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 DTB_Fault_Fault; @@ -489,9 +491,7 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const // only valid in kernel mode if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != AlphaISA::mode_kernel) { - fault(req->vaddr, - ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK), - req->xc); + fault(req, ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK)); if (write) { write_acv++; } else { read_acv++; } return DTB_Acv_Fault; } @@ -516,9 +516,8 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const if (!pte) { // page fault - fault(req->vaddr, - ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK), - req->xc); + fault(req, + (write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK); if (write) { write_misses++; } else { read_misses++; } return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault; } @@ -528,29 +527,25 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const if (write) { if (!(pte->xwe & MODE2MASK(mode))) { // declare the instruction access fault - fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_ACV_MASK | - (pte->fonw ? MM_STAT_FONW_MASK : 0), - req->xc); + fault(req, (MM_STAT_WR_MASK | MM_STAT_ACV_MASK | + (pte->fonw ? MM_STAT_FONW_MASK : 0))); write_acv++; return DTB_Fault_Fault; } if (pte->fonw) { - fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_FONW_MASK, - req->xc); + fault(req, MM_STAT_WR_MASK | MM_STAT_FONW_MASK); write_acv++; return DTB_Fault_Fault; } } else { if (!(pte->xre & MODE2MASK(mode))) { - fault(req->vaddr, - MM_STAT_ACV_MASK | - (pte->fonr ? MM_STAT_FONR_MASK : 0), - req->xc); + fault(req, (MM_STAT_ACV_MASK | + (pte->fonr ? MM_STAT_FONR_MASK : 0))); read_acv++; return DTB_Acv_Fault; } if (pte->fonr) { - fault(req->vaddr, MM_STAT_FONR_MASK, req->xc); + fault(req, MM_STAT_FONR_MASK); read_acv++; return DTB_Fault_Fault; } diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/alpha_memory.hh index 04dd0dcf1..42bc03ddd 100644 --- a/arch/alpha/alpha_memory.hh +++ b/arch/alpha/alpha_memory.hh @@ -112,7 +112,7 @@ class AlphaDTB : public AlphaTLB Stats::Formula accesses; protected: - void fault(Addr pc, uint64_t flags, ExecContext *xc) const; + void fault(MemReqPtr &req, uint64_t flags) const; public: AlphaDTB(const std::string &name, int size); diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc index ecf66f4f5..d2ca71b3a 100644 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@ -162,6 +162,7 @@ AlphaISA::zeroRegisters(XC *xc) void ExecContext::ev5_trap(Fault fault) { + DPRINTF(Fault, "Fault %s\n", FaultName(fault)); Stats::recordEvent(csprintf("Fault %s", FaultName(fault))); assert(!misspeculating()); @@ -302,11 +303,7 @@ ExecContext::readIpr(int idx, Fault &fault) break; case AlphaISA::IPR_VA: - // SFX: unlocks interrupt status registers retval = ipr[idx]; - - if (!misspeculating()) - regs.intrlock = false; break; case AlphaISA::IPR_VA_FORM: diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc index 080699ddb..94f5d9bc3 100644 --- a/arch/alpha/isa_desc +++ b/arch/alpha/isa_desc @@ -1023,7 +1023,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '', # and memory access flags (handled here). # Would be nice to autogenerate this list, but oh well. - valid_mem_flags = ['LOCKED', 'EVICT_NEXT', 'PF_EXCLUSIVE'] + valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE'] inst_flags = [] mem_flags = [] for f in flags: @@ -1072,7 +1072,7 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{ # Declare the prefetch instruction object. # convert flags from tuple to list to make them mutable - pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp'] + pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT'] (pf_header_output, pf_decoder_output, _, pf_exec_output) = \ LoadStoreBase(name, Name + 'Prefetch', ea_code, '', @@ -2391,9 +2391,10 @@ decode OPCODE default Unknown::unknown() { } format MiscPrefetch { - 0xf800: wh64({{ EA = Rb; }}, - {{ xc->writeHint(EA, 64); }}, - IsMemRef, IsStore, MemWriteOp); + 0xf800: wh64({{ EA = Rb & ~ULL(63); }}, + {{ xc->writeHint(EA, 64, memAccessFlags); }}, + IsMemRef, IsDataPrefetch, IsStore, MemWriteOp, + NO_FAULT); } format BasicOperate { diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh index 179e9897f..6559368e4 100644 --- a/arch/alpha/isa_traits.hh +++ b/arch/alpha/isa_traits.hh @@ -153,7 +153,6 @@ class AlphaISA #ifdef FULL_SYSTEM IntReg palregs[NumIntRegs]; // PAL shadow registers InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs - int intrlock; // interrupt register lock flag int intrflag; // interrupt flag bool pal_shadow; // using pal_shadow registers #endif // FULL_SYSTEM |