diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/alpha/alpha_memory.cc | 84 | ||||
-rw-r--r-- | arch/alpha/ev5.hh | 7 | ||||
-rw-r--r-- | arch/alpha/vtophys.cc | 12 |
3 files changed, 69 insertions, 34 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; } } } diff --git a/arch/alpha/ev5.hh b/arch/alpha/ev5.hh index aa3d7e226..bd4115704 100644 --- a/arch/alpha/ev5.hh +++ b/arch/alpha/ev5.hh @@ -57,9 +57,10 @@ #define VA_SPACE(X) (((X) >> 41) & 0x3) #define VA_POFS(X) ((X) & 0x1fff) -#define PA_IMPL_MASK ULL(0xffffffffff) -#define PA_UNCACHED_BIT ULL(0x8000000000) -#define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFF00000)) +#define PA_IMPL_MASK ULL(0xfffffffffff) // for Tsunami +#define PA_UNCACHED_BIT_39 ULL(0x8000000000) +#define PA_UNCACHED_BIT_40 ULL(0x10000000000) +#define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFFF00000)) #define PA_PFN2PA(X) ((X) << 13) diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc index 5e14b06d3..d91d80c83 100644 --- a/arch/alpha/vtophys.cc +++ b/arch/alpha/vtophys.cc @@ -96,20 +96,20 @@ 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 if (!ptbr) { - paddr = vaddr; - } else { +// if (PC_PAL(vaddr)) { +// paddr = vaddr & ~ULL(1); +// } 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); |