diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/alpha/alpha_memory.cc | 96 | ||||
-rw-r--r-- | arch/alpha/alpha_memory.hh | 2 | ||||
-rw-r--r-- | arch/alpha/ev5.cc | 5 | ||||
-rw-r--r-- | arch/alpha/ev5.hh | 31 | ||||
-rw-r--r-- | arch/alpha/isa_desc | 11 | ||||
-rw-r--r-- | arch/alpha/isa_traits.hh | 1 | ||||
-rw-r--r-- | arch/alpha/vtophys.cc | 15 |
7 files changed, 103 insertions, 58 deletions
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index d7004b461..a40ad7a5c 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -101,18 +101,34 @@ AlphaTLB::checkCacheability(MemReqPtr &req) * to catch a weird case where both are used, which shouldn't happen. */ + +#ifdef ALPHA_TLASER + if (req->paddr & PA_UNCACHED_BIT_39) { +#else if (req->paddr & PA_UNCACHED_BIT_43) { +#endif // IPR memory space not implemented - if (PA_IPR_SPACE(req->paddr)) - if (!req->xc->misspeculating()) - panic("IPR memory space not implemented! PA=%x\n", - req->paddr); - - // mark request as uncacheable - req->flags |= UNCACHEABLE; + if (PA_IPR_SPACE(req->paddr)) { + if (!req->xc->misspeculating()) { + switch (req->paddr) { + case ULL(0xFFFFF00188): + req->data = 0; + break; + + default: + panic("IPR memory space not implemented! PA=%x\n", + req->paddr); + } + } + } else { + // mark request as uncacheable + req->flags |= UNCACHEABLE; - // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) - req->paddr &= PA_UNCACHED_MASK; +#ifndef ALPHA_TLASER + // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) + req->paddr &= PA_UNCACHED_MASK; +#endif + } } } @@ -301,7 +317,13 @@ AlphaITB::translate(MemReqPtr &req) const // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5 // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 +#ifdef ALPHA_TLASER + if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && + VA_SPACE_EV5(req->vaddr) == 2) { +#else if (VA_SPACE_EV6(req->vaddr) == 0x7e) { +#endif + // only valid in kernel mode if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) { @@ -312,11 +334,13 @@ AlphaITB::translate(MemReqPtr &req) const req->paddr = req->vaddr & PA_IMPL_MASK; +#ifndef ALPHA_TLASER // sign extend the physical address properly if (req->paddr & PA_UNCACHED_BIT_40) req->paddr |= ULL(0xf0000000000); else req->paddr &= ULL(0xffffffffff); +#endif } else { // not a physical address: need to look up pte @@ -430,12 +454,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 +478,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,35 +502,38 @@ 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; } // Check for "superpage" mapping +#ifdef ALPHA_TLASER + if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && + VA_SPACE_EV5(req->vaddr) == 2) { +#else if (VA_SPACE_EV6(req->vaddr) == 0x7e) { +#endif // 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; } req->paddr = req->vaddr & PA_IMPL_MASK; +#ifndef ALPHA_TLASER // sign extend the physical address properly if (req->paddr & PA_UNCACHED_BIT_40) req->paddr |= ULL(0xf0000000000); else req->paddr &= ULL(0xffffffffff); +#endif } else { if (write) @@ -516,9 +547,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 +558,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/ev5.hh b/arch/alpha/ev5.hh index 517e1111f..5b27dd3dc 100644 --- a/arch/alpha/ev5.hh +++ b/arch/alpha/ev5.hh @@ -32,8 +32,15 @@ #define ALT_MODE_AM(X) (((X) >> 3) & 0x3) #define DTB_CM_CM(X) (((X) >> 3) & 0x3) + +#ifdef ALPHA_TLASER +#define DTB_ASN_ASN(X) (((X) >> 57) & 0x7f) +#define DTB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff) +#else #define DTB_ASN_ASN(X) (((X) >> 57) & 0xff) #define DTB_PTE_PPN(X) (((X) >> 32) & 0x07fffffff) +#endif + #define DTB_PTE_XRE(X) (((X) >> 8) & 0xf) #define DTB_PTE_XWE(X) (((X) >> 12) & 0xf) #define DTB_PTE_FONR(X) (((X) >> 1) & 0x1) @@ -41,9 +48,16 @@ #define DTB_PTE_GH(X) (((X) >> 5) & 0x3) #define DTB_PTE_ASMA(X) (((X) >> 4) & 0x1) -#define ICM_CM(X) (((X) >> 3) & 0x3) +#define ICM_CM(X) (((X) >> 3) & 0x3) + +#ifdef ALPHA_TLASER +#define ITB_ASN_ASN(X) (((X) >> 4) & 0x7f) +#define ITB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff) +#else #define ITB_ASN_ASN(X) (((X) >> 4) & 0xff) #define ITB_PTE_PPN(X) (((X) >> 32) & 0x07fffffff) +#endif + #define ITB_PTE_XRE(X) (((X) >> 8) & 0xf) #define ITB_PTE_FONR(X) (((X) >> 1) & 0x1) #define ITB_PTE_FONW(X) (((X) >> 2) & 0x1) @@ -52,18 +66,23 @@ #define VA_UNIMPL_MASK ULL(0xfffff80000000000) #define VA_IMPL_MASK ULL(0x000007ffffffffff) -#define VA_IMPL(X) ((X) & VA_IMPL_MASK) -#define VA_VPN(X) (VA_IMPL(X) >> 13) +#define VA_IMPL(X) ((X) & VA_IMPL_MASK) +#define VA_VPN(X) (VA_IMPL(X) >> 13) #define VA_SPACE_EV5(X) (((X) >> 41) & 0x3) -#define VA_SPACE_EV6(X) (((X) >> 41) & 0x7f) -#define VA_POFS(X) ((X) & 0x1fff) +#define VA_SPACE_EV6(X) (((X) >> 41) & 0x7f) +#define VA_POFS(X) ((X) & 0x1fff) -#define PA_IMPL_MASK ULL(0xfffffffffff) // for Tsunami #define PA_UNCACHED_BIT_39 ULL(0x8000000000) #define PA_UNCACHED_BIT_40 ULL(0x10000000000) #define PA_UNCACHED_BIT_43 ULL(0x80000000000) #define PA_UNCACHED_MASK ULL(0x807ffffffff) // Clear PA<42:35> +#ifdef ALPHA_TLASER +#define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFF00000)) +#define PA_IMPL_MASK ULL(0xffffffffff) +#else #define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFFF00000)) +#define PA_IMPL_MASK ULL(0xfffffffffff) // for Tsunami +#endif #define PA_PFN2PA(X) ((X) << 13) 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 diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc index cf2ebbf80..7a38b296b 100644 --- a/arch/alpha/vtophys.cc +++ b/arch/alpha/vtophys.cc @@ -96,20 +96,23 @@ vtophys(ExecContext *xc, Addr vaddr) { Addr ptbr = xc->regs.ipr[AlphaISA::IPR_PALtemp20]; Addr paddr = 0; -// if (PC_PAL(vaddr)) { -// paddr = vaddr & ~ULL(1); -// } else { + //@todo Andrew couldn't remember why he commented some of this code + //so I put it back in. Perhaps something to do with gdb debugging? + if (PC_PAL(vaddr)) { + paddr = vaddr & ~ULL(1); + } else if (!ptbr) { + paddr = vaddr; + } else { if (vaddr >= ALPHA_K0SEG_BASE && vaddr <= ALPHA_K0SEG_END) { paddr = ALPHA_K0SEG_TO_PHYS(vaddr); - } else if (!ptbr) { - paddr = vaddr; } else { Addr pte = kernel_pte_lookup(xc->physmem, ptbr, vaddr); uint64_t entry = xc->physmem->phys_read_qword(pte); if (pte && entry_valid(entry)) paddr = PMAP_PTE_PA(entry) | (vaddr & PGOFSET); } -// } + } + DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); |