From: Kevin Lim Date: Tue, 28 Feb 2006 20:16:24 +0000 (-0500) Subject: Merge ktlim@zizzer:/bk/m5 X-Git-Tag: m5_2.0_beta1~87^2~54 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=34da58a698e4119876f04d13c337e9974970f49a;p=gem5.git Merge ktlim@zizzer:/bk/m5 into zamp.eecs.umich.edu:/z/ktlim2/clean/m5-clean arch/alpha/ev5.cc: cpu/o3/regfile.hh: Hand merge. --HG-- rename : arch/alpha/alpha_memory.cc => arch/alpha/tlb.cc extra : convert_revision : c941dd2198851398820b38a66471372ed8454891 --- 34da58a698e4119876f04d13c337e9974970f49a diff --cc arch/alpha/ev5.cc index ca26fc257,f292c6c46..2bb005eb4 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@@ -79,7 -79,7 +79,7 @@@ AlphaISA::initCPU(RegFile *regs, int cp regs->intRegFile[16] = cpuId; regs->intRegFile[0] = cpuId; - regs->pc = regs->ipr[IPR_PAL_BASE] + (new ResetFault)->vect(); - regs->pc = regs->miscRegs.readReg(IPR_PAL_BASE) + fault_addr(ResetFault); ++ regs->pc = regs->miscRegs.readReg(IPR_PAL_BASE) + (new ResetFault)->vect(); regs->npc = regs->pc + sizeof(MachInst); } @@@ -144,12 -157,12 +142,12 @@@ AlphaISA::processInterrupts(CPU *cpu } } - if (ipl && ipl > ipr[IPR_IPLR]) { - ipr[IPR_ISR] = summary; - ipr[IPR_INTID] = ipl; + if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) { + cpu->setMiscReg(IPR_ISR, summary); + cpu->setMiscReg(IPR_INTID, ipl); - cpu->trap(InterruptFault); + cpu->trap(new InterruptFault); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - ipr[IPR_IPLR], ipl, summary); + cpu->readMiscReg(IPR_IPLR), ipl, summary); } } @@@ -174,26 -187,24 +172,25 @@@ ExecContext::ev5_temp_trap(Fault fault assert(!misspeculating()); kernelStats->fault(fault); - if (fault == ArithmeticFault) + if (fault->isA()) panic("Arithmetic traps are unimplemented!"); - AlphaISA::InternalProcReg *ipr = regs.ipr; - // exception restart address - if (fault != InterruptFault || !inPalMode()) + if (!fault->isA() || !inPalMode()) - ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc; + setMiscReg(AlphaISA::IPR_EXC_ADDR, regs.pc); - if (fault == PalFault || fault == ArithmeticFault /* || + if (fault->isA() || fault->isA() /* || fault == InterruptFault && !inPalMode() */) { - // traps... skip faulting instruction + // traps... skip faulting instruction. - ipr[AlphaISA::IPR_EXC_ADDR] += 4; + setMiscReg(AlphaISA::IPR_EXC_ADDR, + readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4); } if (!inPalMode()) AlphaISA::swap_palshadow(®s, true); - regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + - regs.pc = readMiscReg(AlphaISA::IPR_PAL_BASE) + AlphaISA::fault_addr(fault); ++ regs.pc = readMiscReg(AlphaISA::IPR_PAL_BASE) + + (dynamic_cast(fault.get()))->vect(); regs.npc = regs.pc + sizeof(MachInst); } @@@ -201,27 -212,26 +198,26 @@@ void AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc) { - InternalProcReg *ipr = regs->ipr; bool use_pc = (fault == NoFault); - if (fault == ArithmeticFault) + if (fault->isA()) panic("arithmetic faults NYI..."); // compute exception restart address - if (use_pc || fault == PalFault || fault == ArithmeticFault) { + if (use_pc || fault->isA() || fault->isA()) { // traps... skip faulting instruction - ipr[IPR_EXC_ADDR] = regs->pc + 4; + regs->miscRegs.setReg(IPR_EXC_ADDR, regs->pc + 4); } else { // fault, post fault at excepting instruction - ipr[IPR_EXC_ADDR] = regs->pc; + regs->miscRegs.setReg(IPR_EXC_ADDR, regs->pc); } // jump to expection address (PAL PC bit set here as well...) if (!use_pc) - regs->npc = ipr[IPR_PAL_BASE] + + regs->npc = regs->miscRegs.readReg(IPR_PAL_BASE) + - fault_addr(fault); + (dynamic_cast(fault.get()))->vect(); else - regs->npc = ipr[IPR_PAL_BASE] + pc; + regs->npc = regs->miscRegs.readReg(IPR_PAL_BASE) + pc; // that's it! (orders of magnitude less painful than x86) } @@@ -229,12 -239,10 +225,10 @@@ Fault ExecContext::hwrei() { - uint64_t *ipr = regs.ipr; - if (!inPalMode()) - return UnimplementedOpcodeFault; + return new UnimplementedOpcodeFault; - setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]); + setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR)); if (!misspeculating()) { kernelStats->hwrei(); diff --cc arch/alpha/isa/decoder.isa index cdcf96215,c72f14a71..ca38dca92 --- a/arch/alpha/isa/decoder.isa +++ b/arch/alpha/isa/decoder.isa @@@ -670,10 -670,10 +670,10 @@@ decode OPCODE default Unknown::unknown( 0x00: CallPal::call_pal({{ if (!palValid || (palPriv - && xc->readIpr(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) { + && xc->readMiscRegWithEffect(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) { // invalid pal function code, or attempt to do privileged // PAL call in non-kernel mode - fault = UnimplementedOpcodeFault; + fault = new UnimplementedOpcodeFault; } else { // check to see if simulator wants to do something special @@@ -729,19 -729,19 +729,19 @@@ 0x19: hw_mfpr({{ // this instruction is only valid in PAL mode if (!xc->inPalMode()) { - fault = UnimplementedOpcodeFault; + fault = new UnimplementedOpcodeFault; } else { - Ra = xc->readIpr(ipr_index, fault); + Ra = xc->readMiscRegWithEffect(ipr_index, fault); } }}); 0x1d: hw_mtpr({{ // this instruction is only valid in PAL mode if (!xc->inPalMode()) { - fault = UnimplementedOpcodeFault; + fault = new UnimplementedOpcodeFault; } else { - xc->setIpr(ipr_index, Ra); + xc->setMiscRegWithEffect(ipr_index, Ra); if (traceData) { traceData->setData(Ra); } } }}); diff --cc arch/alpha/isa/fp.isa index 2ee714b0f,20a564045..13656359f --- a/arch/alpha/isa/fp.isa +++ b/arch/alpha/isa/fp.isa @@@ -35,8 -35,8 +35,8 @@@ output exec { inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { Fault fault = NoFault; // dummy... this ipr access should not fault - if (!EV5::ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) { + if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR, fault))) { - fault = FloatEnableFault; + fault = new FloatEnableFault; } return fault; } diff --cc arch/alpha/tlb.cc index 8297737bd,000000000..0f2cedc83 mode 100644,000000..100644 --- a/arch/alpha/tlb.cc +++ b/arch/alpha/tlb.cc @@@ -1,683 -1,0 +1,686 @@@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "arch/alpha/tlb.hh" +#include "base/inifile.hh" +#include "base/str.hh" +#include "base/trace.hh" +#include "config/alpha_tlaser.hh" +#include "cpu/exec_context.hh" +#include "sim/builder.hh" + +using namespace std; +using namespace EV5; + +/////////////////////////////////////////////////////////////////////// +// +// Alpha TLB +// +#ifdef DEBUG +bool uncacheBit39 = false; +bool uncacheBit40 = false; +#endif + +#define MODE2MASK(X) (1 << (X)) + +AlphaTLB::AlphaTLB(const string &name, int s) + : SimObject(name), size(s), nlu(0) +{ + table = new AlphaISA::PTE[size]; + memset(table, 0, sizeof(AlphaISA::PTE[size])); +} + +AlphaTLB::~AlphaTLB() +{ + if (table) + delete [] table; +} + +// look up an entry in the TLB +AlphaISA::PTE * +AlphaTLB::lookup(Addr vpn, uint8_t asn) const +{ + // assume not found... + AlphaISA::PTE *retval = NULL; + + PageTable::const_iterator i = lookupTable.find(vpn); + if (i != lookupTable.end()) { + while (i->first == vpn) { + int index = i->second; + AlphaISA::PTE *pte = &table[index]; + assert(pte->valid); + if (vpn == pte->tag && (pte->asma || pte->asn == asn)) { + retval = pte; + break; + } + + ++i; + } + } + + DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, + retval ? "hit" : "miss", retval ? retval->ppn : 0); + return retval; +} + + +void +AlphaTLB::checkCacheability(MemReqPtr &req) +{ + // in Alpha, cacheability is controlled by upper-level bits of the + // physical address + + /* + * 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 ALPHA_TLASER + if (req->paddr & PAddrUncachedBit39) { +#else + if (req->paddr & PAddrUncachedBit43) { +#endif + // IPR memory space not implemented + if (PAddrIprSpace(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; + +#if !ALPHA_TLASER + // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) + req->paddr &= PAddrUncachedMask; +#endif + } + } +} + + +// insert a new TLB entry +void +AlphaTLB::insert(Addr addr, AlphaISA::PTE &pte) +{ + AlphaISA::VAddr vaddr = addr; + if (table[nlu].valid) { + Addr oldvpn = table[nlu].tag; + PageTable::iterator i = lookupTable.find(oldvpn); + + if (i == lookupTable.end()) + panic("TLB entry not found in lookupTable"); + + int index; + while ((index = i->second) != nlu) { + if (table[index].tag != oldvpn) + panic("TLB entry not found in lookupTable"); + + ++i; + } + + DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); + + lookupTable.erase(i); + } + + DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn); + + table[nlu] = pte; + table[nlu].tag = vaddr.vpn(); + table[nlu].valid = true; + + lookupTable.insert(make_pair(vaddr.vpn(), nlu)); + nextnlu(); +} + +void +AlphaTLB::flushAll() +{ + DPRINTF(TLB, "flushAll\n"); + memset(table, 0, sizeof(AlphaISA::PTE[size])); + lookupTable.clear(); + nlu = 0; +} + +void +AlphaTLB::flushProcesses() +{ + PageTable::iterator i = lookupTable.begin(); + PageTable::iterator end = lookupTable.end(); + while (i != end) { + int index = i->second; + AlphaISA::PTE *pte = &table[index]; + assert(pte->valid); + + // we can't increment i after we erase it, so save a copy and + // increment it to get the next entry now + PageTable::iterator cur = i; + ++i; + + if (!pte->asma) { + DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn); + pte->valid = false; + lookupTable.erase(cur); + } + } +} + +void +AlphaTLB::flushAddr(Addr addr, uint8_t asn) +{ + AlphaISA::VAddr vaddr = addr; + + PageTable::iterator i = lookupTable.find(vaddr.vpn()); + if (i == lookupTable.end()) + return; + + while (i->first == vaddr.vpn()) { + int index = i->second; + AlphaISA::PTE *pte = &table[index]; + assert(pte->valid); + + if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) { + DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), + pte->ppn); + + // invalidate this entry + pte->valid = false; + + lookupTable.erase(i); + } + + ++i; + } +} + + +void +AlphaTLB::serialize(ostream &os) +{ + SERIALIZE_SCALAR(size); + SERIALIZE_SCALAR(nlu); + + for (int i = 0; i < size; i++) { + nameOut(os, csprintf("%s.PTE%d", name(), i)); + table[i].serialize(os); + } +} + +void +AlphaTLB::unserialize(Checkpoint *cp, const string §ion) +{ + UNSERIALIZE_SCALAR(size); + UNSERIALIZE_SCALAR(nlu); + + for (int i = 0; i < size; i++) { + table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); + if (table[i].valid) { + lookupTable.insert(make_pair(table[i].tag, i)); + } + } +} + + +/////////////////////////////////////////////////////////////////////// +// +// Alpha ITB +// +AlphaITB::AlphaITB(const std::string &name, int size) + : AlphaTLB(name, size) +{} + + +void +AlphaITB::regStats() +{ + hits + .name(name() + ".hits") + .desc("ITB hits"); + misses + .name(name() + ".misses") + .desc("ITB misses"); + acv + .name(name() + ".acv") + .desc("ITB acv"); + accesses + .name(name() + ".accesses") + .desc("ITB accesses"); + + accesses = hits + misses; +} + +void +AlphaITB::fault(Addr pc, ExecContext *xc) const +{ - uint64_t *ipr = xc->regs.ipr; - + if (!xc->misspeculating()) { - ipr[AlphaISA::IPR_ITB_TAG] = pc; - ipr[AlphaISA::IPR_IFAULT_VA_FORM] = - ipr[AlphaISA::IPR_IVPTBR] | (AlphaISA::VAddr(pc).vpn() << 3); ++ xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc); ++ xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM, ++ xc->readMiscReg(AlphaISA::IPR_IVPTBR) | ++ (AlphaISA::VAddr(pc).vpn() << 3)); + } +} + + +Fault +AlphaITB::translate(MemReqPtr &req) const +{ - InternalProcReg *ipr = req->xc->regs.ipr; ++ ExecContext *xc = req->xc; + + if (AlphaISA::PcPAL(req->vaddr)) { + // strip off PAL PC marker (lsb is 1) + req->paddr = (req->vaddr & ~3) & PAddrImplMask; + hits++; + return NoFault; + } + + if (req->flags & PHYSICAL) { + req->paddr = req->vaddr; + } else { + // verify that this is a good virtual address + if (!validVirtualAddress(req->vaddr)) { + fault(req->vaddr, req->xc); + acv++; + return new ItbAcvFault; + } + + + // 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 +#if ALPHA_TLASER - if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && ++ if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) && + VAddrSpaceEV5(req->vaddr) == 2) { +#else + if (VAddrSpaceEV6(req->vaddr) == 0x7e) { +#endif + // only valid in kernel mode - if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != ++ if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) != + AlphaISA::mode_kernel) { + fault(req->vaddr, req->xc); + acv++; + return new ItbAcvFault; + } + + req->paddr = req->vaddr & PAddrImplMask; + +#if !ALPHA_TLASER + // sign extend the physical address properly + if (req->paddr & PAddrUncachedBit40) + req->paddr |= ULL(0xf0000000000); + else + req->paddr &= ULL(0xffffffffff); +#endif + + } else { + // not a physical address: need to look up pte ++ int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN)); + AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(), - DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); ++ asn); + + if (!pte) { + fault(req->vaddr, req->xc); + misses++; + return new ItbPageFault; + } + + req->paddr = (pte->ppn << AlphaISA::PageShift) + + (AlphaISA::VAddr(req->vaddr).offset() & ~3); + + // check permissions for this access - if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) { ++ if (!(pte->xre & ++ (1 << ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM))))) { + // instruction access fault + fault(req->vaddr, req->xc); + acv++; + return new ItbAcvFault; + } + + hits++; + } + } + + // check that the physical address is ok (catch bad physical addresses) + if (req->paddr & ~PAddrImplMask) + return genMachineCheckFault(); + + checkCacheability(req); + + return NoFault; +} + +/////////////////////////////////////////////////////////////////////// +// +// Alpha DTB +// +AlphaDTB::AlphaDTB(const std::string &name, int size) + : AlphaTLB(name, size) +{} + +void +AlphaDTB::regStats() +{ + read_hits + .name(name() + ".read_hits") + .desc("DTB read hits") + ; + + read_misses + .name(name() + ".read_misses") + .desc("DTB read misses") + ; + + read_acv + .name(name() + ".read_acv") + .desc("DTB read access violations") + ; + + read_accesses + .name(name() + ".read_accesses") + .desc("DTB read accesses") + ; + + write_hits + .name(name() + ".write_hits") + .desc("DTB write hits") + ; + + write_misses + .name(name() + ".write_misses") + .desc("DTB write misses") + ; + + write_acv + .name(name() + ".write_acv") + .desc("DTB write access violations") + ; + + write_accesses + .name(name() + ".write_accesses") + .desc("DTB write accesses") + ; + + hits + .name(name() + ".hits") + .desc("DTB hits") + ; + + misses + .name(name() + ".misses") + .desc("DTB misses") + ; + + acv + .name(name() + ".acv") + .desc("DTB access violations") + ; + + accesses + .name(name() + ".accesses") + .desc("DTB accesses") + ; + + hits = read_hits + write_hits; + misses = read_misses + write_misses; + acv = read_acv + write_acv; + accesses = read_accesses + write_accesses; +} + +void +AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const +{ + ExecContext *xc = req->xc; + AlphaISA::VAddr vaddr = req->vaddr; - uint64_t *ipr = xc->regs.ipr; + + // 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] = req->vaddr; ++ xc->setMiscReg(AlphaISA::IPR_VA, req->vaddr); + + // set MM_STAT register flags - ipr[AlphaISA::IPR_MM_STAT] = ++ xc->setMiscReg(AlphaISA::IPR_MM_STAT, + (((Opcode(xc->getInst()) & 0x3f) << 11) + | ((Ra(xc->getInst()) & 0x1f) << 6) - | (flags & 0x3f)); ++ | (flags & 0x3f))); + + // set VA_FORM register with faulting formatted address - ipr[AlphaISA::IPR_VA_FORM] = - ipr[AlphaISA::IPR_MVPTBR] | (vaddr.vpn() << 3); ++ xc->setMiscReg(AlphaISA::IPR_VA_FORM, ++ xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3)); + } +} + +Fault +AlphaDTB::translate(MemReqPtr &req, bool write) const +{ + RegFile *regs = &req->xc->regs; ++ ExecContext *xc = req->xc; + Addr pc = regs->pc; - InternalProcReg *ipr = regs->ipr; + + AlphaISA::mode_type mode = - (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]); ++ (AlphaISA::mode_type)DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)); + + + /** + * Check for alignment faults + */ + if (req->vaddr & (req->size - 1)) { + fault(req, write ? MM_STAT_WR_MASK : 0); + DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr, + req->size); + return genAlignmentFault(); + } + + if (pc & 0x1) { + mode = (req->flags & ALTMODE) ? - (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE]) ++ (AlphaISA::mode_type)ALT_MODE_AM( ++ xc->readMiscReg(AlphaISA::IPR_ALT_MODE)) + : AlphaISA::mode_kernel; + } + + if (req->flags & PHYSICAL) { + req->paddr = req->vaddr; + } else { + // verify that this is a good virtual address + if (!validVirtualAddress(req->vaddr)) { + 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 new DtbPageFault; + } + + // Check for "superpage" mapping +#if ALPHA_TLASER - if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && ++ if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) && + VAddrSpaceEV5(req->vaddr) == 2) { +#else + if (VAddrSpaceEV6(req->vaddr) == 0x7e) { +#endif + + // only valid in kernel mode - if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != ++ if (DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)) != + AlphaISA::mode_kernel) { + fault(req, ((write ? MM_STAT_WR_MASK : 0) | + MM_STAT_ACV_MASK)); + if (write) { write_acv++; } else { read_acv++; } + return new DtbAcvFault; + } + + req->paddr = req->vaddr & PAddrImplMask; + +#if !ALPHA_TLASER + // sign extend the physical address properly + if (req->paddr & PAddrUncachedBit40) + req->paddr |= ULL(0xf0000000000); + else + req->paddr &= ULL(0xffffffffff); +#endif + + } else { + if (write) + write_accesses++; + else + read_accesses++; + ++ int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN)); ++ + // not a physical address: need to look up pte + AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(), - DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); ++ asn); + + if (!pte) { + // page fault + fault(req, (write ? MM_STAT_WR_MASK : 0) | + MM_STAT_DTB_MISS_MASK); + if (write) { write_misses++; } else { read_misses++; } + return (req->flags & VPTE) ? + (Fault)(new PDtbMissFault) : + (Fault)(new NDtbMissFault); + } + + req->paddr = (pte->ppn << AlphaISA::PageShift) + + AlphaISA::VAddr(req->vaddr).offset(); + + if (write) { + if (!(pte->xwe & MODE2MASK(mode))) { + // declare the instruction access fault + fault(req, MM_STAT_WR_MASK | + MM_STAT_ACV_MASK | + (pte->fonw ? MM_STAT_FONW_MASK : 0)); + write_acv++; + return new DtbPageFault; + } + if (pte->fonw) { + fault(req, MM_STAT_WR_MASK | + MM_STAT_FONW_MASK); + write_acv++; + return new DtbPageFault; + } + } else { + if (!(pte->xre & MODE2MASK(mode))) { + fault(req, MM_STAT_ACV_MASK | + (pte->fonr ? MM_STAT_FONR_MASK : 0)); + read_acv++; + return new DtbAcvFault; + } + if (pte->fonr) { + fault(req, MM_STAT_FONR_MASK); + read_acv++; + return new DtbPageFault; + } + } + } + + if (write) + write_hits++; + else + read_hits++; + } + + // check that the physical address is ok (catch bad physical addresses) + if (req->paddr & ~PAddrImplMask) + return genMachineCheckFault(); + + checkCacheability(req); + + return NoFault; +} + +AlphaISA::PTE & +AlphaTLB::index(bool advance) +{ + AlphaISA::PTE *pte = &table[nlu]; + + if (advance) + nextnlu(); + + return *pte; +} + +DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB) + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB) + + Param size; + +END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB) + +BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB) + + INIT_PARAM_DFLT(size, "TLB size", 48) + +END_INIT_SIM_OBJECT_PARAMS(AlphaITB) + + +CREATE_SIM_OBJECT(AlphaITB) +{ + return new AlphaITB(getInstanceName(), size); +} + +REGISTER_SIM_OBJECT("AlphaITB", AlphaITB) + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB) + + Param size; + +END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB) + +BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB) + + INIT_PARAM_DFLT(size, "TLB size", 64) + +END_INIT_SIM_OBJECT_PARAMS(AlphaDTB) + + +CREATE_SIM_OBJECT(AlphaDTB) +{ + return new AlphaDTB(getInstanceName(), size); +} + +REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB) + diff --cc cpu/o3/alpha_cpu_impl.hh index 9b7cd8a0e,bd4e34914..daa61bb1c --- a/cpu/o3/alpha_cpu_impl.hh +++ b/cpu/o3/alpha_cpu_impl.hh @@@ -277,12 -256,10 +256,10 @@@ template ::hwrei() { - uint64_t *ipr = getIpr(); - if (!inPalMode()) - return UnimplementedOpcodeFault; + return new UnimplementedOpcodeFault; - this->setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]); + this->setNextPC(this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR)); // kernelStats.hwrei(); @@@ -329,31 -306,32 +306,32 @@@ AlphaFullCPU::trap(Fault fault // miss uint64_t PC = this->commit.readCommitPC(); - DPRINTF(Fault, "Fault %s\n", fault ? fault->name : "name"); - this->recordEvent(csprintf("Fault %s", fault ? fault->name : "name")); + DPRINTF(Fault, "Fault %s\n", fault->name()); + this->recordEvent(csprintf("Fault %s", fault->name())); -// kernelStats.fault(fault); + //kernelStats.fault(fault); - if (fault == ArithmeticFault) + if (fault->isA()) panic("Arithmetic traps are unimplemented!"); - AlphaISA::InternalProcReg *ipr = getIpr(); - // exception restart address - Get the commit PC - if (fault != InterruptFault || !inPalMode(PC)) + if (!fault->isA() || !inPalMode(PC)) - ipr[AlphaISA::IPR_EXC_ADDR] = PC; + this->regFile.miscRegs.setReg(AlphaISA::IPR_EXC_ADDR, PC); - if (fault == PalFault || fault == ArithmeticFault /* || + if (fault->isA() || fault->isA() /* || fault == InterruptFault && !PC_PAL(regs.pc) */) { // traps... skip faulting instruction - ipr[AlphaISA::IPR_EXC_ADDR] += 4; + AlphaISA::MiscReg ipr_exc_addr = + this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR); + this->regFile.miscRegs.setReg(AlphaISA::IPR_EXC_ADDR, + ipr_exc_addr + 4); } if (!inPalMode(PC)) swapPALShadow(true); - this->regFile.setPC( ipr[AlphaISA::IPR_PAL_BASE] + + this->regFile.setPC(this->regFile.miscRegs.readReg(AlphaISA::IPR_PAL_BASE) + - AlphaISA::fault_addr(fault) ); + (dynamic_cast(fault.get()))->vect()); this->regFile.setNextPC(PC + sizeof(MachInst)); } diff --cc cpu/simple/cpu.cc index 1f362876f,dd2d53c17..d826c589e --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@@ -682,16 -681,16 +681,16 @@@ SimpleCPU::tick( } } - if (ipr[IPR_ASTRR]) + if (xc->readMiscReg(IPR_ASTRR)) panic("asynchronous traps not implemented\n"); - if (ipl && ipl > xc->regs.ipr[IPR_IPLR]) { - ipr[IPR_ISR] = summary; - ipr[IPR_INTID] = ipl; + if (ipl && ipl > xc->readMiscReg(IPR_IPLR)) { + xc->setMiscReg(IPR_ISR, summary); + xc->setMiscReg(IPR_INTID, ipl); - xc->ev5_trap(InterruptFault); + (new InterruptFault)->ev5_trap(xc); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - ipr[IPR_IPLR], ipl, summary); + xc->readMiscReg(IPR_IPLR), ipl, summary); } } #endif