diff options
Diffstat (limited to 'arch/alpha/alpha_memory.cc')
-rw-r--r-- | arch/alpha/alpha_memory.cc | 47 |
1 files changed, 21 insertions, 26 deletions
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index 23815bf01..58aa13b8f 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -415,12 +415,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; @@ -432,9 +439,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; } } @@ -459,10 +463,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; @@ -476,9 +478,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; } @@ -496,9 +496,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; } @@ -508,29 +507,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; } |