diff options
Diffstat (limited to 'arch/alpha/ev5.cc')
-rw-r--r-- | arch/alpha/ev5.cc | 249 |
1 files changed, 78 insertions, 171 deletions
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc index 125affd03..019e83dd4 100644 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@ -26,7 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "arch/alpha/alpha_memory.hh" +#include "arch/alpha/tlb.hh" #include "arch/alpha/isa_traits.hh" #include "arch/alpha/osfpal.hh" #include "base/kgdb.h" @@ -34,6 +34,7 @@ #include "base/stats/events.hh" #include "config/full_system.hh" #include "cpu/base.hh" +#include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" #include "cpu/fast/cpu.hh" #include "kern/kernel_stats.hh" @@ -46,83 +47,34 @@ using namespace EV5; //////////////////////////////////////////////////////////////////////// // -// -// -void -AlphaISA::swap_palshadow(RegFile *regs, bool use_shadow) -{ - if (regs->pal_shadow == use_shadow) - panic("swap_palshadow: wrong PAL shadow state"); - - regs->pal_shadow = use_shadow; - - for (int i = 0; i < NumIntRegs; i++) { - if (reg_redir[i]) { - IntReg temp = regs->intRegFile[i]; - regs->intRegFile[i] = regs->palregs[i]; - regs->palregs[i] = temp; - } - } -} - -//////////////////////////////////////////////////////////////////////// -// // Machine dependent functions // void -AlphaISA::initCPU(RegFile *regs) +AlphaISA::initCPU(ExecContext *xc, int cpuId) { - initIPRs(regs); - // CPU comes up with PAL regs enabled - swap_palshadow(regs, true); + initIPRs(xc, cpuId); - regs->pc = regs->ipr[IPR_PAL_BASE] + fault_addr[Reset_Fault]; - regs->npc = regs->pc + sizeof(MachInst); -} + xc->setIntReg(16, cpuId); + xc->setIntReg(0, cpuId); -//////////////////////////////////////////////////////////////////////// -// -// alpha exceptions - value equals trap address, update with MD_FAULT_TYPE -// -Addr -AlphaISA::fault_addr[Num_Faults] = { - 0x0000, /* No_Fault */ - 0x0001, /* Reset_Fault */ - 0x0401, /* Machine_Check_Fault */ - 0x0501, /* Arithmetic_Fault */ - 0x0101, /* Interrupt_Fault */ - 0x0201, /* Ndtb_Miss_Fault */ - 0x0281, /* Pdtb_Miss_Fault */ - 0x0301, /* Alignment_Fault */ - 0x0381, /* DTB_Fault_Fault */ - 0x0381, /* DTB_Acv_Fault */ - 0x0181, /* ITB_Miss_Fault */ - 0x0181, /* ITB_Fault_Fault */ - 0x0081, /* ITB_Acv_Fault */ - 0x0481, /* Unimplemented_Opcode_Fault */ - 0x0581, /* Fen_Fault */ - 0x2001, /* Pal_Fault */ - 0x0501, /* Integer_Overflow_Fault: maps to Arithmetic_Fault */ -}; - -const int AlphaISA::reg_redir[AlphaISA::NumIntRegs] = { - /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 8 */ 1, 1, 1, 1, 1, 1, 1, 0, - /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 24 */ 0, 1, 0, 0, 0, 0, 0, 0 }; + xc->setPC(xc->readMiscReg(IPR_PAL_BASE) + (new ResetFault)->vect()); + xc->setNextPC(xc->readPC() + sizeof(MachInst)); +} //////////////////////////////////////////////////////////////////////// // // // void -AlphaISA::initIPRs(RegFile *regs) +AlphaISA::initIPRs(ExecContext *xc, int cpuId) { - uint64_t *ipr = regs->ipr; + for (int i = 0; i < NumInternalProcRegs; ++i) { + xc->setMiscReg(i, 0); + } - bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg)); - ipr[IPR_PAL_BASE] = PalBase; - ipr[IPR_MCSR] = 0x6; + xc->setMiscReg(IPR_PAL_BASE, PalBase); + xc->setMiscReg(IPR_MCSR, 0x6); + xc->setMiscReg(IPR_PALtemp16, cpuId); } @@ -134,17 +86,16 @@ AlphaISA::processInterrupts(CPU *cpu) //Handle the interrupts int ipl = 0; int summary = 0; - IntReg *ipr = cpu->getIprPtr(); cpu->checkInterrupts = false; - if (ipr[IPR_ASTRR]) + if (cpu->readMiscReg(IPR_ASTRR)) panic("asynchronous traps not implemented\n"); - if (ipr[IPR_SIRR]) { + if (cpu->readMiscReg(IPR_SIRR)) { for (int i = INTLEVEL_SOFTWARE_MIN; i < INTLEVEL_SOFTWARE_MAX; i++) { - if (ipr[IPR_SIRR] & (ULL(1) << i)) { + if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { // See table 4-19 of the 21164 hardware reference ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); @@ -165,12 +116,12 @@ AlphaISA::processInterrupts(CPU *cpu) } } - if (ipl && ipl > ipr[IPR_IPLR]) { - ipr[IPR_ISR] = summary; - ipr[IPR_INTID] = ipl; - cpu->trap(Interrupt_Fault); + if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) { + cpu->setMiscReg(IPR_ISR, summary); + cpu->setMiscReg(IPR_INTID, ipl); + 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); } } @@ -182,96 +133,43 @@ AlphaISA::zeroRegisters(CPU *cpu) // Insure ISA semantics // (no longer very clean due to the change in setIntReg() in the // cpu model. Consider changing later.) - cpu->xc->setIntReg(ZeroReg, 0); - cpu->xc->setFloatRegDouble(ZeroReg, 0.0); + cpu->cpuXC->setIntReg(ZeroReg, 0); + cpu->cpuXC->setFloatRegDouble(ZeroReg, 0.0); } -void -ExecContext::ev5_trap(Fault fault) +Fault +CPUExecContext::hwrei() { - DPRINTF(Fault, "Fault %s at PC: %#x\n", FaultName(fault), regs.pc); - cpu->recordEvent(csprintf("Fault %s", FaultName(fault))); - - assert(!misspeculating()); - kernelStats->fault(fault); - - if (fault == Arithmetic_Fault) - panic("Arithmetic traps are unimplemented!"); + if (!inPalMode()) + return new UnimplementedOpcodeFault; - AlphaISA::InternalProcReg *ipr = regs.ipr; + setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR)); - // exception restart address - if (fault != Interrupt_Fault || !inPalMode()) - ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc; + if (!misspeculating()) { + cpu->kernelStats->hwrei(); - if (fault == Pal_Fault || fault == Arithmetic_Fault /* || - fault == Interrupt_Fault && !inPalMode() */) { - // traps... skip faulting instruction - ipr[AlphaISA::IPR_EXC_ADDR] += 4; + cpu->checkInterrupts = true; } - if (!inPalMode()) - AlphaISA::swap_palshadow(®s, true); - - regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault]; - regs.npc = regs.pc + sizeof(MachInst); + // FIXME: XXX check for interrupts? XXX + return NoFault; } - -void -AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc) +int +AlphaISA::MiscRegFile::getInstAsid() { - InternalProcReg *ipr = regs->ipr; - bool use_pc = (fault == No_Fault); - - if (fault == Arithmetic_Fault) - panic("arithmetic faults NYI..."); - - // compute exception restart address - if (use_pc || fault == Pal_Fault || fault == Arithmetic_Fault) { - // traps... skip faulting instruction - ipr[IPR_EXC_ADDR] = regs->pc + 4; - } else { - // fault, post fault at excepting instruction - ipr[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] + fault_addr[fault]; - else - regs->npc = ipr[IPR_PAL_BASE] + pc; - - // that's it! (orders of magnitude less painful than x86) + return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); } -Fault -ExecContext::hwrei() +int +AlphaISA::MiscRegFile::getDataAsid() { - uint64_t *ipr = regs.ipr; - - if (!inPalMode()) - return Unimplemented_Opcode_Fault; - - setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]); - - if (!misspeculating()) { - kernelStats->hwrei(); - - if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0) - AlphaISA::swap_palshadow(®s, false); - - cpu->checkInterrupts = true; - } - - // FIXME: XXX check for interrupts? XXX - return No_Fault; + return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); } -uint64_t -ExecContext::readIpr(int idx, Fault &fault) +AlphaISA::MiscReg +AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ExecContext *xc) { - uint64_t *ipr = regs.ipr; uint64_t retval = 0; // return value, default 0 switch (idx) { @@ -324,7 +222,7 @@ ExecContext::readIpr(int idx, Fault &fault) case AlphaISA::IPR_CC: retval |= ipr[idx] & ULL(0xffffffff00000000); - retval |= cpu->curCycle() & ULL(0x00000000ffffffff); + retval |= xc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff); break; case AlphaISA::IPR_VA: @@ -341,7 +239,7 @@ ExecContext::readIpr(int idx, Fault &fault) case AlphaISA::IPR_DTB_PTE: { - AlphaISA::PTE &pte = dtb->index(!misspeculating()); + AlphaISA::PTE &pte = xc->getDTBPtr()->index(!xc->misspeculating()); retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32; retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8; @@ -363,12 +261,12 @@ ExecContext::readIpr(int idx, Fault &fault) case AlphaISA::IPR_DTB_IAP: case AlphaISA::IPR_ITB_IA: case AlphaISA::IPR_ITB_IAP: - fault = Unimplemented_Opcode_Fault; + fault = new UnimplementedOpcodeFault; break; default: // invalid IPR - fault = Unimplemented_Opcode_Fault; + fault = new UnimplementedOpcodeFault; break; } @@ -381,13 +279,12 @@ int break_ipl = -1; #endif Fault -ExecContext::setIpr(int idx, uint64_t val) +AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc) { - uint64_t *ipr = regs.ipr; uint64_t old; - if (misspeculating()) - return No_Fault; + if (xc->misspeculating()) + return NoFault; switch (idx) { case AlphaISA::IPR_PALtemp0: @@ -439,7 +336,7 @@ ExecContext::setIpr(int idx, uint64_t val) // write entire quad w/ no side-effect old = ipr[idx]; ipr[idx] = val; - kernelStats->context(old, val); + xc->getCpuPtr()->kernelStats->context(old, val, xc); break; case AlphaISA::IPR_DTB_PTE: @@ -466,14 +363,14 @@ ExecContext::setIpr(int idx, uint64_t val) // only write least significant five bits - interrupt level ipr[idx] = val & 0x1f; - kernelStats->swpipl(ipr[idx]); + xc->getCpuPtr()->kernelStats->swpipl(ipr[idx]); break; case AlphaISA::IPR_DTB_CM: if (val & 0x18) - kernelStats->mode(Kernel::user); + xc->getCpuPtr()->kernelStats->mode(Kernel::user, xc); else - kernelStats->mode(Kernel::kernel); + xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc); case AlphaISA::IPR_ICM: // only write two mode bits - processor mode @@ -533,7 +430,7 @@ ExecContext::setIpr(int idx, uint64_t val) case AlphaISA::IPR_ITB_PTE_TEMP: case AlphaISA::IPR_DTB_PTE_TEMP: // read-only registers - return Unimplemented_Opcode_Fault; + return new UnimplementedOpcodeFault; case AlphaISA::IPR_HWINT_CLR: case AlphaISA::IPR_SL_XMIT: @@ -547,21 +444,22 @@ ExecContext::setIpr(int idx, uint64_t val) // really a control write ipr[idx] = 0; - dtb->flushAll(); + xc->getDTBPtr()->flushAll(); break; case AlphaISA::IPR_DTB_IAP: // really a control write ipr[idx] = 0; - dtb->flushProcesses(); + xc->getDTBPtr()->flushProcesses(); break; case AlphaISA::IPR_DTB_IS: // really a control write ipr[idx] = val; - dtb->flushAddr(val, DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); + xc->getDTBPtr()->flushAddr(val, + DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); break; case AlphaISA::IPR_DTB_TAG: { @@ -584,7 +482,7 @@ ExecContext::setIpr(int idx, uint64_t val) pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]); // insert new TAG/PTE value into data TLB - dtb->insert(val, pte); + xc->getDTBPtr()->insert(val, pte); } break; @@ -608,7 +506,7 @@ ExecContext::setIpr(int idx, uint64_t val) pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]); // insert new TAG/PTE value into data TLB - itb->insert(ipr[AlphaISA::IPR_ITB_TAG], pte); + xc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], pte); } break; @@ -616,30 +514,39 @@ ExecContext::setIpr(int idx, uint64_t val) // really a control write ipr[idx] = 0; - itb->flushAll(); + xc->getITBPtr()->flushAll(); break; case AlphaISA::IPR_ITB_IAP: // really a control write ipr[idx] = 0; - itb->flushProcesses(); + xc->getITBPtr()->flushProcesses(); break; case AlphaISA::IPR_ITB_IS: // really a control write ipr[idx] = val; - itb->flushAddr(val, ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN])); + xc->getITBPtr()->flushAddr(val, + ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN])); break; default: // invalid IPR - return Unimplemented_Opcode_Fault; + return new UnimplementedOpcodeFault; } // no error... - return No_Fault; + return NoFault; +} + +void +AlphaISA::MiscRegFile::copyIprs(ExecContext *xc) +{ + for (int i = IPR_Base_DepTag; i < NumInternalProcRegs; ++i) { + ipr[i] = xc->readMiscReg(i); + } } /** @@ -647,9 +554,9 @@ ExecContext::setIpr(int idx, uint64_t val) * If return value is false, actual PAL call will be suppressed. */ bool -ExecContext::simPalCheck(int palFunc) +CPUExecContext::simPalCheck(int palFunc) { - kernelStats->callpal(palFunc); + cpu->kernelStats->callpal(palFunc, proxy); switch (palFunc) { case PAL::halt: |