diff options
Diffstat (limited to 'arch/alpha/alpha_memory.cc')
-rw-r--r-- | arch/alpha/alpha_memory.cc | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index 1608cc4a4..63fb3ebcb 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -87,24 +87,42 @@ AlphaTLB::checkCacheability(MemReqPtr &req) { // in Alpha, cacheability is controlled by upper-level bits of the // physical address - if (req->paddr & PA_UNCACHED_BIT) { - if (PA_IPR_SPACE(req->paddr)) { - // IPR memory space not implemented - 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; + + /* + * We support having the uncacheable bit in either bit 39 or bit 40. + * The Turbolaser platform (and EV5) support having the bit in 39, but + * Tsunami (which Linux assumes uses an EV6) generates accesses with + * the bit in 40. So we must check for both, but we have debug flags + * to catch a weird case where both are used, which shouldn't happen. + */ + + if (req->paddr & PA_UNCACHED_BIT_40 || + req->paddr & PA_UNCACHED_BIT_39) { + +#ifdef DEBUG + if (req->paddr & PA_UNCACHED_BIT_40) { + if(uncacheBit39) + panic("Bit 40 access follows bit 39 access, PA=%x\n", + req->paddr); + + uncacheBit40 = true; + } else if (req->paddr & PA_UNCACHED_BIT_39) { + if(uncacheBit40) + panic("Bit 39 acceess follows bit 40 access, PA=%x\n", + req->paddr); + + uncacheBit39 = true; } +#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; } } @@ -299,10 +317,18 @@ AlphaITB::translate(MemReqPtr &req) const if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) { fault(req->vaddr, req->xc); acv++; - return ITB_Acv_Fault; + return Itb_Acv_Fault; } req->paddr = req->vaddr & PA_IMPL_MASK; + + // sign extend the physical address properly + if (req->paddr & PA_UNCACHED_BIT_39 || + req->paddr & PA_UNCACHED_BIT_40) + req->paddr |= 0xf0000000000ULL; + else + req->paddr &= 0xffffffffffULL; + } else { // not a physical address: need to look up pte AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr), @@ -311,7 +337,7 @@ AlphaITB::translate(MemReqPtr &req) const if (!pte) { fault(req->vaddr, req->xc); misses++; - return ITB_Fault_Fault; + return Itb_Fault_Fault; } req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3); @@ -321,7 +347,7 @@ AlphaITB::translate(MemReqPtr &req) const // instruction access fault fault(req->vaddr, req->xc); acv++; - return ITB_Acv_Fault; + return Itb_Acv_Fault; } hits++; @@ -480,10 +506,18 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK), req->xc); if (write) { write_acv++; } else { read_acv++; } - return DTB_Acv_Fault; + return Dtb_Acv_Fault; } req->paddr = req->vaddr & PA_IMPL_MASK; + + // sign extend the physical address properly + if (req->paddr & PA_UNCACHED_BIT_39 || + req->paddr & PA_UNCACHED_BIT_40) + req->paddr |= 0xf0000000000ULL; + else + req->paddr &= 0xffffffffffULL; + } else { if (write) write_accesses++; @@ -512,13 +546,13 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const (pte->fonw ? MM_STAT_FONW_MASK : 0), req->xc); write_acv++; - return DTB_Fault_Fault; + return Dtb_Fault_Fault; } if (pte->fonw) { fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_FONW_MASK, req->xc); write_acv++; - return DTB_Fault_Fault; + return Dtb_Fault_Fault; } } else { if (!(pte->xre & MODE2MASK(mode))) { @@ -527,12 +561,12 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const (pte->fonr ? MM_STAT_FONR_MASK : 0), req->xc); read_acv++; - return DTB_Acv_Fault; + return Dtb_Acv_Fault; } if (pte->fonr) { fault(req->vaddr, MM_STAT_FONR_MASK, req->xc); read_acv++; - return DTB_Fault_Fault; + return Dtb_Fault_Fault; } } } |