diff options
Diffstat (limited to 'src')
91 files changed, 1953 insertions, 1189 deletions
diff --git a/src/arch/alpha/SConscript b/src/arch/alpha/SConscript index 4f293e22f..04bac3996 100644 --- a/src/arch/alpha/SConscript +++ b/src/arch/alpha/SConscript @@ -32,27 +32,28 @@ Import('*') if env['TARGET_ISA'] == 'alpha': + Source('ev5.cc') Source('faults.cc') Source('floatregfile.cc') Source('intregfile.cc') + Source('ipr.cc') Source('miscregfile.cc') + Source('pagetable.cc') Source('regfile.cc') Source('remote_gdb.cc') + Source('tlb.cc') Source('utility.cc') + SimObject('AlphaTLB.py') + if env['FULL_SYSTEM']: SimObject('AlphaSystem.py') - SimObject('AlphaTLB.py') - Source('ev5.cc') Source('idle_event.cc') - Source('ipr.cc') Source('kernel_stats.cc') Source('osfpal.cc') - Source('pagetable.cc') Source('stacktrace.cc') Source('system.cc') - Source('tlb.cc') Source('vtophys.cc') Source('freebsd/system.cc') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 86b8fd2d0..5dc49623e 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -68,22 +68,6 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId) delete reset; } -//////////////////////////////////////////////////////////////////////// -// -// -// -void -AlphaISA::initIPRs(ThreadContext *tc, int cpuId) -{ - for (int i = 0; i < NumInternalProcRegs; ++i) { - tc->setMiscRegNoEffect(i, 0); - } - - tc->setMiscRegNoEffect(IPR_PAL_BASE, PalBase); - tc->setMiscRegNoEffect(IPR_MCSR, 0x6); - tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId); -} - template <class CPU> void @@ -171,6 +155,24 @@ AlphaISA::MiscRegFile::getDataAsid() return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); } +#endif + +//////////////////////////////////////////////////////////////////////// +// +// +// +void +AlphaISA::initIPRs(ThreadContext *tc, int cpuId) +{ + for (int i = 0; i < NumInternalProcRegs; ++i) { + tc->setMiscRegNoEffect(i, 0); + } + + tc->setMiscRegNoEffect(IPR_PAL_BASE, EV5::PalBase); + tc->setMiscRegNoEffect(IPR_MCSR, 0x6); + tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId); +} + AlphaISA::MiscReg AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc) { @@ -243,15 +245,16 @@ AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc) case AlphaISA::IPR_DTB_PTE: { - AlphaISA::PTE &pte = tc->getDTBPtr()->index(!tc->misspeculating()); - - retval |= ((uint64_t)pte.ppn & ULL(0x7ffffff)) << 32; - retval |= ((uint64_t)pte.xre & ULL(0xf)) << 8; - retval |= ((uint64_t)pte.xwe & ULL(0xf)) << 12; - retval |= ((uint64_t)pte.fonr & ULL(0x1)) << 1; - retval |= ((uint64_t)pte.fonw & ULL(0x1))<< 2; - retval |= ((uint64_t)pte.asma & ULL(0x1)) << 4; - retval |= ((uint64_t)pte.asn & ULL(0x7f)) << 57; + AlphaISA::TlbEntry &entry + = tc->getDTBPtr()->index(!tc->misspeculating()); + + retval |= ((uint64_t)entry.ppn & ULL(0x7ffffff)) << 32; + retval |= ((uint64_t)entry.xre & ULL(0xf)) << 8; + retval |= ((uint64_t)entry.xwe & ULL(0xf)) << 12; + retval |= ((uint64_t)entry.fonr & ULL(0x1)) << 1; + retval |= ((uint64_t)entry.fonw & ULL(0x1))<< 2; + retval |= ((uint64_t)entry.asma & ULL(0x1)) << 4; + retval |= ((uint64_t)entry.asn & ULL(0x7f)) << 57; } break; @@ -340,8 +343,10 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) // write entire quad w/ no side-effect old = ipr[idx]; ipr[idx] = val; +#if FULL_SYSTEM if (tc->getKernelStats()) tc->getKernelStats()->context(old, val, tc); +#endif break; case AlphaISA::IPR_DTB_PTE: @@ -368,11 +373,14 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) // only write least significant five bits - interrupt level ipr[idx] = val & 0x1f; +#if FULL_SYSTEM if (tc->getKernelStats()) tc->getKernelStats()->swpipl(ipr[idx]); +#endif break; case AlphaISA::IPR_DTB_CM: +#if FULL_SYSTEM if (val & 0x18) { if (tc->getKernelStats()) tc->getKernelStats()->mode(TheISA::Kernel::user, tc); @@ -380,6 +388,7 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) if (tc->getKernelStats()) tc->getKernelStats()->mode(TheISA::Kernel::kernel, tc); } +#endif case AlphaISA::IPR_ICM: // only write two mode bits - processor mode @@ -468,54 +477,54 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) ipr[idx] = val; tc->getDTBPtr()->flushAddr(val, - DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); + EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); break; case AlphaISA::IPR_DTB_TAG: { - struct AlphaISA::PTE pte; + struct AlphaISA::TlbEntry entry; // FIXME: granularity hints NYI... - if (DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0) + if (EV5::DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0) panic("PTE GH field != 0"); // write entire quad ipr[idx] = val; // construct PTE for new entry - pte.ppn = DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]); - pte.xre = DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]); - pte.xwe = DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]); - pte.fonr = DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]); - pte.fonw = DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]); - pte.asma = DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]); - pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]); + entry.ppn = EV5::DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]); + entry.xre = EV5::DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]); + entry.xwe = EV5::DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]); + entry.fonr = EV5::DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]); + entry.fonw = EV5::DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]); + entry.asma = EV5::DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]); + entry.asn = EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]); // insert new TAG/PTE value into data TLB - tc->getDTBPtr()->insert(val, pte); + tc->getDTBPtr()->insert(val, entry); } break; case AlphaISA::IPR_ITB_PTE: { - struct AlphaISA::PTE pte; + struct AlphaISA::TlbEntry entry; // FIXME: granularity hints NYI... - if (ITB_PTE_GH(val) != 0) + if (EV5::ITB_PTE_GH(val) != 0) panic("PTE GH field != 0"); // write entire quad ipr[idx] = val; // construct PTE for new entry - pte.ppn = ITB_PTE_PPN(val); - pte.xre = ITB_PTE_XRE(val); - pte.xwe = 0; - pte.fonr = ITB_PTE_FONR(val); - pte.fonw = ITB_PTE_FONW(val); - pte.asma = ITB_PTE_ASMA(val); - pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]); + entry.ppn = EV5::ITB_PTE_PPN(val); + entry.xre = EV5::ITB_PTE_XRE(val); + entry.xwe = 0; + entry.fonr = EV5::ITB_PTE_FONR(val); + entry.fonw = EV5::ITB_PTE_FONW(val); + entry.asma = EV5::ITB_PTE_ASMA(val); + entry.asn = EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]); // insert new TAG/PTE value into data TLB - tc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], pte); + tc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], entry); } break; @@ -538,7 +547,7 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) ipr[idx] = val; tc->getITBPtr()->flushAddr(val, - ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN])); + EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN])); break; default: @@ -558,6 +567,7 @@ AlphaISA::copyIprs(ThreadContext *src, ThreadContext *dest) } } +#if FULL_SYSTEM /** * Check for special simulator handling of specific PAL calls. diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index 149729351..7d4de902a 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -29,13 +29,13 @@ * Kevin Lim */ +#include "arch/alpha/ev5.hh" #include "arch/alpha/faults.hh" +#include "arch/alpha/tlb.hh" #include "cpu/thread_context.hh" #include "cpu/base.hh" #include "base/trace.hh" -#if FULL_SYSTEM -#include "arch/alpha/ev5.hh" -#else +#if !FULL_SYSTEM #include "sim/process.hh" #include "mem/page_table.hh" #endif @@ -83,10 +83,6 @@ FaultName DtbAlignmentFault::_name = "unalign"; FaultVect DtbAlignmentFault::_vect = 0x0301; FaultStat DtbAlignmentFault::_count; -FaultName ItbMissFault::_name = "itbmiss"; -FaultVect ItbMissFault::_vect = 0x0181; -FaultStat ItbMissFault::_count; - FaultName ItbPageFault::_name = "itbmiss"; FaultVect ItbPageFault::_vect = 0x0181; FaultStat ItbPageFault::_count; @@ -176,6 +172,63 @@ void ItbFault::invoke(ThreadContext * tc) AlphaFault::invoke(tc); } +#else + +void ItbPageFault::invoke(ThreadContext * tc) +{ + Process *p = tc->getProcessPtr(); + Addr physaddr; + bool success = p->pTable->translate(pc, physaddr); + if(!success) { + panic("Tried to execute unmapped address %#x.\n", pc); + } else { + VAddr vaddr(pc); + VAddr paddr(physaddr); + + TlbEntry entry; + entry.tag = vaddr.vpn(); + entry.ppn = paddr.vpn(); + entry.xre = 15; //This can be read in all modes. + entry.xwe = 1; //This can be written only in kernel mode. + entry.asn = p->M5_pid; //Address space number. + entry.asma = false; //Only match on this ASN. + entry.fonr = false; //Don't fault on read. + entry.fonw = false; //Don't fault on write. + entry.valid = true; //This entry is valid. + + tc->getITBPtr()->insert(vaddr.page(), entry); + } +} + +void NDtbMissFault::invoke(ThreadContext * tc) +{ + Process *p = tc->getProcessPtr(); + Addr physaddr; + bool success = p->pTable->translate(vaddr, physaddr); + if(!success) { + p->checkAndAllocNextPage(vaddr); + success = p->pTable->translate(vaddr, physaddr); + } + if(!success) { + panic("Tried to access unmapped address %#x.\n", (Addr)vaddr); + } else { + VAddr paddr(physaddr); + + TlbEntry entry; + entry.tag = vaddr.vpn(); + entry.ppn = paddr.vpn(); + entry.xre = 15; //This can be read in all modes. + entry.xwe = 15; //This can be written in all modes. + entry.asn = p->M5_pid; //Address space number. + entry.asma = false; //Only match on this ASN. + entry.fonr = false; //Don't fault on read. + entry.fonw = false; //Don't fault on write. + entry.valid = true; //This entry is valid. + + tc->getDTBPtr()->insert(vaddr.page(), entry); + } +} + #endif } // namespace AlphaISA diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh index ed0c3a6b1..74699b2b5 100644 --- a/src/arch/alpha/faults.hh +++ b/src/arch/alpha/faults.hh @@ -35,9 +35,7 @@ #include "config/full_system.hh" #include "sim/faults.hh" -#if FULL_SYSTEM #include "arch/alpha/pagetable.hh" -#endif // The design of the "name" and "vect" functions is in sim/faults.hh @@ -90,11 +88,6 @@ static inline Fault genMachineCheckFault() return new MachineCheckFault; } -static inline Fault genAlignmentFault() -{ - return new AlignmentFault; -} - class ResetFault : public AlphaFault { private: @@ -140,8 +133,7 @@ class InterruptFault : public AlphaFault class DtbFault : public AlphaFault { -#if FULL_SYSTEM - private: + protected: AlphaISA::VAddr vaddr; uint32_t reqFlags; uint64_t flags; @@ -149,7 +141,6 @@ class DtbFault : public AlphaFault DtbFault(AlphaISA::VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags) : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags) { } -#endif FaultName name() const = 0; FaultVect vect() = 0; FaultStat & countStat() = 0; @@ -165,14 +156,15 @@ class NDtbMissFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: -#if FULL_SYSTEM NDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } -#endif FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} +#if !FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif }; class PDtbMissFault : public DtbFault @@ -182,11 +174,9 @@ class PDtbMissFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: -#if FULL_SYSTEM PDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } -#endif FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} @@ -199,11 +189,9 @@ class DtbPageFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: -#if FULL_SYSTEM DtbPageFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } -#endif FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} @@ -216,11 +204,9 @@ class DtbAcvFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: -#if FULL_SYSTEM DtbAcvFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } -#endif FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} @@ -233,11 +219,9 @@ class DtbAlignmentFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: -#if FULL_SYSTEM DtbAlignmentFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } -#endif FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} @@ -245,7 +229,7 @@ class DtbAlignmentFault : public DtbFault class ItbFault : public AlphaFault { - private: + protected: Addr pc; public: ItbFault(Addr _pc) @@ -259,21 +243,6 @@ class ItbFault : public AlphaFault #endif }; -class ItbMissFault : public ItbFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - ItbMissFault(Addr pc) - : ItbFault(pc) - { } - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; - class ItbPageFault : public ItbFault { private: @@ -287,6 +256,9 @@ class ItbPageFault : public ItbFault FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} +#if !FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif }; class ItbAcvFault : public ItbFault diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh index 7dc7e5151..53eea5f69 100644 --- a/src/arch/alpha/isa_traits.hh +++ b/src/arch/alpha/isa_traits.hh @@ -63,14 +63,13 @@ namespace AlphaISA const Addr PageMask = ~(PageBytes - 1); const Addr PageOffset = PageBytes - 1; -#if FULL_SYSTEM //////////////////////////////////////////////////////////////////////// // // Translation stuff // - const Addr PteShift = 3; + const Addr PteShift = 3; const Addr NPtePageShift = PageShift - PteShift; const Addr NPtePage = ULL(1) << NPtePageShift; const Addr PteMask = NPtePage - 1; @@ -90,6 +89,8 @@ namespace AlphaISA // For loading... XXX This maybe could be USegEnd?? --ali const Addr LoadAddrMask = ULL(0xffffffffff); +#if FULL_SYSTEM + //////////////////////////////////////////////////////////////////////// // // Interrupt levels @@ -114,6 +115,8 @@ namespace AlphaISA NumInterruptLevels = INTLEVEL_EXTERNAL_MAX }; +#endif + // EV5 modes enum mode_type { @@ -124,8 +127,6 @@ namespace AlphaISA mode_number // number of modes }; -#endif - // Constants Related to the number of registers const int NumIntArchRegs = 32; diff --git a/src/arch/alpha/miscregfile.cc b/src/arch/alpha/miscregfile.cc index 1af97adcf..cb5875349 100644 --- a/src/arch/alpha/miscregfile.cc +++ b/src/arch/alpha/miscregfile.cc @@ -43,9 +43,7 @@ namespace AlphaISA SERIALIZE_SCALAR(uniq); SERIALIZE_SCALAR(lock_flag); SERIALIZE_SCALAR(lock_addr); -#if FULL_SYSTEM SERIALIZE_ARRAY(ipr, NumInternalProcRegs); -#endif } void @@ -55,9 +53,7 @@ namespace AlphaISA UNSERIALIZE_SCALAR(uniq); UNSERIALIZE_SCALAR(lock_flag); UNSERIALIZE_SCALAR(lock_addr); -#if FULL_SYSTEM UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs); -#endif } MiscReg @@ -74,15 +70,9 @@ namespace AlphaISA return lock_addr; case MISCREG_INTR: return intr_flag; -#if FULL_SYSTEM default: assert(misc_reg < NumInternalProcRegs); return ipr[misc_reg]; -#else - default: - panic("Attempt to read an invalid misc register!"); - return 0; -#endif } } @@ -100,14 +90,8 @@ namespace AlphaISA return lock_addr; case MISCREG_INTR: return intr_flag; -#if FULL_SYSTEM default: return readIpr(misc_reg, tc); -#else - default: - panic("No faulting misc regs in SE mode!"); - return 0; -#endif } } @@ -130,15 +114,10 @@ namespace AlphaISA case MISCREG_INTR: intr_flag = val; return; -#if FULL_SYSTEM default: assert(misc_reg < NumInternalProcRegs); ipr[misc_reg] = val; return; -#else - default: - panic("Attempt to write to an invalid misc register!"); -#endif } } @@ -163,11 +142,7 @@ namespace AlphaISA intr_flag = val; return; default: -#if FULL_SYSTEM setIpr(misc_reg, val, tc); -#else - panic("No registers with side effects in SE mode!"); -#endif return; } } diff --git a/src/arch/alpha/miscregfile.hh b/src/arch/alpha/miscregfile.hh index aea702849..022b6404a 100644 --- a/src/arch/alpha/miscregfile.hh +++ b/src/arch/alpha/miscregfile.hh @@ -34,7 +34,6 @@ #include "arch/alpha/ipr.hh" #include "arch/alpha/types.hh" -#include "config/full_system.hh" #include "sim/host.hh" #include "sim/serialize.hh" @@ -70,9 +69,7 @@ namespace AlphaISA public: MiscRegFile() { -#if FULL_SYSTEM initializeIprTable(); -#endif } MiscReg readRegNoEffect(int misc_reg); @@ -100,7 +97,6 @@ namespace AlphaISA void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); -#if FULL_SYSTEM protected: typedef uint64_t InternalProcReg; @@ -110,13 +106,10 @@ namespace AlphaISA InternalProcReg readIpr(int idx, ThreadContext *tc); void setIpr(int idx, InternalProcReg val, ThreadContext *tc); -#endif friend class RegFile; }; -#if FULL_SYSTEM void copyIprs(ThreadContext *src, ThreadContext *dest); -#endif } diff --git a/src/arch/alpha/pagetable.cc b/src/arch/alpha/pagetable.cc index 0c26ccbe3..3f9537834 100644 --- a/src/arch/alpha/pagetable.cc +++ b/src/arch/alpha/pagetable.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2006-2007 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,7 +34,7 @@ namespace AlphaISA { void - PTE::serialize(std::ostream &os) + TlbEntry::serialize(std::ostream &os) { SERIALIZE_SCALAR(tag); SERIALIZE_SCALAR(ppn); @@ -48,7 +48,7 @@ namespace AlphaISA } void - PTE::unserialize(Checkpoint *cp, const std::string §ion) + TlbEntry::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_SCALAR(tag); UNSERIALIZE_SCALAR(ppn); diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh index c7e1c8923..4375f24f1 100644 --- a/src/arch/alpha/pagetable.hh +++ b/src/arch/alpha/pagetable.hh @@ -89,9 +89,16 @@ namespace AlphaISA { Addr paddr() const { return _pfn() << PageShift; } }; - // ITB/DTB page table entry - struct PTE + // ITB/DTB table entry + struct TlbEntry { + Addr pageStart; + //Construct an entry that maps to physical address addr. + TlbEntry(Addr addr) : pageStart(addr) + {} + TlbEntry() + {} + Addr tag; // virtual page number tag Addr ppn; // physical page number uint8_t xre; // read permissions - VMEM_PERM_* mask diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 85619e493..a9848ebb5 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -71,6 +71,12 @@ AlphaLiveProcess::startup() argsInit(MachineBytes, VMPageSize); threadContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer()); + //Opperate in user mode + threadContexts[0]->setMiscRegNoEffect(IPR_ICM, 0x18); + //No super page mapping + threadContexts[0]->setMiscRegNoEffect(IPR_MCSR, 0); + //Set this to 0 for now, but it should be unique for each process + threadContexts[0]->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57); } diff --git a/src/arch/alpha/regfile.cc b/src/arch/alpha/regfile.cc index 3b42ca9bc..2653310d7 100644 --- a/src/arch/alpha/regfile.cc +++ b/src/arch/alpha/regfile.cc @@ -94,8 +94,6 @@ namespace AlphaISA dest->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR, src->readMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR)); -#if FULL_SYSTEM copyIprs(src, dest); -#endif } } diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index f701c423d..628d7ad6b 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -62,8 +62,8 @@ bool uncacheBit40 = false; TLB::TLB(const string &name, int s) : SimObject(name), size(s), nlu(0) { - table = new PTE[size]; - memset(table, 0, sizeof(PTE[size])); + table = new TlbEntry[size]; + memset(table, 0, sizeof(TlbEntry[size])); flushCache(); } @@ -74,23 +74,23 @@ TLB::~TLB() } // look up an entry in the TLB -PTE * +TlbEntry * TLB::lookup(Addr vpn, uint8_t asn) { // assume not found... - PTE *retval = NULL; - - if (PTECache[0]) { - if (vpn == PTECache[0]->tag && - (PTECache[0]->asma || PTECache[0]->asn == asn)) - retval = PTECache[0]; - else if (PTECache[1]) { - if (vpn == PTECache[1]->tag && - (PTECache[1]->asma || PTECache[1]->asn == asn)) - retval = PTECache[1]; - else if (PTECache[2] && vpn == PTECache[2]->tag && - (PTECache[2]->asma || PTECache[2]->asn == asn)) - retval = PTECache[2]; + TlbEntry *retval = NULL; + + if (EntryCache[0]) { + if (vpn == EntryCache[0]->tag && + (EntryCache[0]->asma || EntryCache[0]->asn == asn)) + retval = EntryCache[0]; + else if (EntryCache[1]) { + if (vpn == EntryCache[1]->tag && + (EntryCache[1]->asma || EntryCache[1]->asn == asn)) + retval = EntryCache[1]; + else if (EntryCache[2] && vpn == EntryCache[2]->tag && + (EntryCache[2]->asma || EntryCache[2]->asn == asn)) + retval = EntryCache[2]; } } @@ -99,10 +99,10 @@ TLB::lookup(Addr vpn, uint8_t asn) if (i != lookupTable.end()) { while (i->first == vpn) { int index = i->second; - PTE *pte = &table[index]; - assert(pte->valid); - if (vpn == pte->tag && (pte->asma || pte->asn == asn)) { - retval = updateCache(pte); + TlbEntry *entry = &table[index]; + assert(entry->valid); + if (vpn == entry->tag && (entry->asma || entry->asn == asn)) { + retval = updateCache(entry); break; } @@ -157,7 +157,7 @@ TLB::checkCacheability(RequestPtr &req) // insert a new TLB entry void -TLB::insert(Addr addr, PTE &pte) +TLB::insert(Addr addr, TlbEntry &entry) { flushCache(); VAddr vaddr = addr; @@ -181,9 +181,9 @@ TLB::insert(Addr addr, PTE &pte) lookupTable.erase(i); } - DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn); + DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), entry.ppn); - table[nlu] = pte; + table[nlu] = entry; table[nlu].tag = vaddr.vpn(); table[nlu].valid = true; @@ -195,7 +195,7 @@ void TLB::flushAll() { DPRINTF(TLB, "flushAll\n"); - memset(table, 0, sizeof(PTE[size])); + memset(table, 0, sizeof(TlbEntry[size])); flushCache(); lookupTable.clear(); nlu = 0; @@ -209,17 +209,17 @@ TLB::flushProcesses() PageTable::iterator end = lookupTable.end(); while (i != end) { int index = i->second; - PTE *pte = &table[index]; - assert(pte->valid); + TlbEntry *entry = &table[index]; + assert(entry->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; + if (!entry->asma) { + DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, entry->tag, entry->ppn); + entry->valid = false; lookupTable.erase(cur); } } @@ -237,15 +237,15 @@ TLB::flushAddr(Addr addr, uint8_t asn) while (i != lookupTable.end() && i->first == vaddr.vpn()) { int index = i->second; - PTE *pte = &table[index]; - assert(pte->valid); + TlbEntry *entry = &table[index]; + assert(entry->valid); - if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) { + if (vaddr.vpn() == entry->tag && (entry->asma || entry->asn == asn)) { DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), - pte->ppn); + entry->ppn); // invalidate this entry - pte->valid = false; + entry->valid = false; lookupTable.erase(i++); } else { @@ -262,7 +262,7 @@ TLB::serialize(ostream &os) SERIALIZE_SCALAR(nlu); for (int i = 0; i < size; i++) { - nameOut(os, csprintf("%s.PTE%d", name(), i)); + nameOut(os, csprintf("%s.Entry%d", name(), i)); table[i].serialize(os); } } @@ -274,7 +274,7 @@ TLB::unserialize(Checkpoint *cp, const string §ion) UNSERIALIZE_SCALAR(nlu); for (int i = 0; i < size; i++) { - table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); + table[i].unserialize(cp, csprintf("%s.Entry%d", section, i)); if (table[i].valid) { lookupTable.insert(make_pair(table[i].tag, i)); } @@ -364,20 +364,20 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) } else { // not a physical address: need to look up pte int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); - PTE *pte = lookup(VAddr(req->getVaddr()).vpn(), + TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(), asn); - if (!pte) { + if (!entry) { misses++; return new ItbPageFault(req->getVaddr()); } - req->setPaddr((pte->ppn << PageShift) + + req->setPaddr((entry->ppn << PageShift) + (VAddr(req->getVaddr()).offset() & ~3)); // check permissions for this access - if (!(pte->xre & + if (!(entry->xre & (1 << ICM_CM(tc->readMiscRegNoEffect(IPR_ICM))))) { // instruction access fault acv++; @@ -548,10 +548,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); // not a physical address: need to look up pte - PTE *pte = lookup(VAddr(req->getVaddr()).vpn(), - asn); + TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(), asn); - if (!pte) { + if (!entry) { // page fault if (write) { write_misses++; } else { read_misses++; } uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | @@ -563,32 +562,32 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) flags)); } - req->setPaddr((pte->ppn << PageShift) + + req->setPaddr((entry->ppn << PageShift) + VAddr(req->getVaddr()).offset()); if (write) { - if (!(pte->xwe & MODE2MASK(mode))) { + if (!(entry->xwe & MODE2MASK(mode))) { // declare the instruction access fault write_acv++; uint64_t flags = MM_STAT_WR_MASK | MM_STAT_ACV_MASK | - (pte->fonw ? MM_STAT_FONW_MASK : 0); + (entry->fonw ? MM_STAT_FONW_MASK : 0); return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); } - if (pte->fonw) { + if (entry->fonw) { write_acv++; uint64_t flags = MM_STAT_WR_MASK | MM_STAT_FONW_MASK; return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); } } else { - if (!(pte->xre & MODE2MASK(mode))) { + if (!(entry->xre & MODE2MASK(mode))) { read_acv++; uint64_t flags = MM_STAT_ACV_MASK | - (pte->fonr ? MM_STAT_FONR_MASK : 0); + (entry->fonr ? MM_STAT_FONR_MASK : 0); return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); } - if (pte->fonr) { + if (entry->fonr) { read_acv++; uint64_t flags = MM_STAT_FONR_MASK; return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); @@ -609,15 +608,15 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) return checkCacheability(req); } -PTE & +TlbEntry & TLB::index(bool advance) { - PTE *pte = &table[nlu]; + TlbEntry *entry = &table[nlu]; if (advance) nextnlu(); - return *pte; + return *entry; } /* end namespace AlphaISA */ } diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index a4255f3c5..8df47dbec 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -48,20 +48,20 @@ class ThreadContext; namespace AlphaISA { - class PTE; + class TlbEntry; class TLB : public SimObject { protected: typedef std::multimap<Addr, int> PageTable; - PageTable lookupTable; // Quick lookup into page table + PageTable lookupTable; // Quick lookup into page table - PTE *table; // the Page Table - int size; // TLB Size - int nlu; // not last used entry (for replacement) + TlbEntry *table; // the Page Table + int size; // TLB Size + int nlu; // not last used entry (for replacement) void nextnlu() { if (++nlu >= size) nlu = 0; } - PTE *lookup(Addr vpn, uint8_t asn); + TlbEntry *lookup(Addr vpn, uint8_t asn); public: TLB(const std::string &name, int size); @@ -69,8 +69,8 @@ namespace AlphaISA int getsize() const { return size; } - PTE &index(bool advance = true); - void insert(Addr vaddr, PTE &pte); + TlbEntry &index(bool advance = true); + void insert(Addr vaddr, TlbEntry &entry); void flushAll(); void flushProcesses(); @@ -90,13 +90,17 @@ namespace AlphaISA virtual void unserialize(Checkpoint *cp, const std::string §ion); // Most recently used page table entries - PTE *PTECache[3]; - inline void flushCache() { memset(PTECache, 0, 3 * sizeof(PTE*)); } - inline PTE* updateCache(PTE *pte) { - PTECache[2] = PTECache[1]; - PTECache[1] = PTECache[0]; - PTECache[0] = pte; - return pte; + TlbEntry *EntryCache[3]; + inline void flushCache() + { + memset(EntryCache, 0, 3 * sizeof(TlbEntry*)); + } + + inline TlbEntry* updateCache(TlbEntry *entry) { + EntryCache[2] = EntryCache[1]; + EntryCache[1] = EntryCache[0]; + EntryCache[0] = entry; + return entry; } }; diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 5d461a0f9..11357bc44 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -115,7 +115,6 @@ namespace AlphaISA inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(0); } -#if FULL_SYSTEM //////////////////////////////////////////////////////////////////////// // @@ -142,8 +141,9 @@ namespace AlphaISA RoundPage(Addr addr) { return (addr + PageBytes - 1) & ~(PageBytes - 1); } - void initCPU(ThreadContext *tc, int cpuId); void initIPRs(ThreadContext *tc, int cpuId); +#if FULL_SYSTEM + void initCPU(ThreadContext *tc, int cpuId); /** * Function to check for and process any interrupts. diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py index 32dd79fdf..925e6b585 100644 --- a/src/arch/micro_asm.py +++ b/src/arch/micro_asm.py @@ -140,9 +140,9 @@ def handle_statement(parser, container, statement): raise try: for label in statement.labels: - container.labels[label.name] = microop + container.labels[label.text] = microop if label.extern: - container.externs[label.name] = microop + container.externs[label.text] = microop container.add_microop(microop) except: print_error("Error adding microop.") @@ -439,6 +439,11 @@ def p_labels_1(t): t[1].append(t[2]) t[0] = t[1] +# labels on lines by themselves are attached to the following instruction. +def p_labels_2(t): + 'labels : labels NEWLINE' + t[0] = t[1] + def p_label_0(t): 'label : ID COLON' label = Label() diff --git a/src/arch/mips/MipsTLB.py b/src/arch/mips/MipsTLB.py new file mode 100644 index 000000000..8c1a00abe --- /dev/null +++ b/src/arch/mips/MipsTLB.py @@ -0,0 +1,20 @@ +from m5.SimObject import SimObject +from m5.params import * +class MipsTLB(SimObject): + type = 'MipsTLB' + abstract = True + #size = Param.Int("TLB size") + +class MipsDTB(MipsTLB): + type = 'MipsDTB' + cxx_namespace = 'MipsISA' + cxx_class = 'DTB' + + #size = 64 + +class MipsITB(MipsTLB): + type = 'MipsITB' + cxx_namespace = 'MipsISA' + cxx_class = 'ITB' + + #size = 64 diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript index 658710389..e1d2146eb 100644 --- a/src/arch/mips/SConscript +++ b/src/arch/mips/SConscript @@ -33,12 +33,15 @@ Import('*') if env['TARGET_ISA'] == 'mips': + Source('dsp.cc') Source('faults.cc') Source('regfile/int_regfile.cc') Source('regfile/misc_regfile.cc') Source('regfile/regfile.cc') + Source('tlb.cc') Source('utility.cc') - Source('dsp.cc') + + SimObject('MipsTLB.py') if env['FULL_SYSTEM']: #Insert Full-System Files Here diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc index 39a2fa997..3d83a21aa 100644 --- a/src/arch/mips/faults.cc +++ b/src/arch/mips/faults.cc @@ -75,12 +75,6 @@ FaultName UnimplementedOpcodeFault::_name = "opdec"; FaultVect UnimplementedOpcodeFault::_vect = 0x0481; FaultStat UnimplementedOpcodeFault::_count; -#if !FULL_SYSTEM -//FaultName PageTableFault::_name = "page_table_fault"; -//FaultVect PageTableFault::_vect = 0x0000; -//FaultStat PageTableFault::_count; -#endif - FaultName InterruptFault::_name = "interrupt"; FaultVect InterruptFault::_vect = 0x0101; FaultStat InterruptFault::_count; @@ -125,40 +119,6 @@ FaultName DspStateDisabledFault::_name = "intover"; FaultVect DspStateDisabledFault::_vect = 0x001a; FaultStat DspStateDisabledFault::_count; - -/*void PageTableFault::invoke(ThreadContext *tc) -{ - Process *p = tc->getProcessPtr(); - - Addr page_addr = p->pTable->pageAlign(vaddr); - - warn("%i: [tid:%i]: %s encountered @ addr %x. Allocating new page for address range %x - %x.\n", - curTick, tc->getThreadNum(), name(), vaddr, page_addr, page_addr+VMPageSize); - - p->pTable->allocate(page_addr, VMPageSize); - - return; -} -*/ - /* address is higher than the stack region or in the current stack region - if (vaddr > p->stack_base || vaddr > p->stack_min) - FaultBase::invoke(tc); - - // We've accessed the next page - if (vaddr > p->stack_min - PageBytes) { - p->stack_min -= PageBytes; - if (p->stack_base - p->stack_min > 8*1024*1024) { - warn("Already allocated Over max stack size for one thread\n"); - } - warn("%i: Allocating page for range %x - %x", - curTick, p->stack_min, p->stack_min-PageBytes); - - p->pTable->allocate(p->stack_min, PageBytes); - warn("Increasing stack size by one page."); - } else { - FaultBase::invoke(tc); - }*/ - void ResetFault::invoke(ThreadContext *tc) { warn("[tid:%i]: %s encountered.\n", tc->getThreadNum(), name()); diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh index 2e5aa81d6..441e7c27f 100644 --- a/src/arch/mips/faults.hh +++ b/src/arch/mips/faults.hh @@ -92,40 +92,11 @@ class UnimplementedOpcodeFault : public MipsFault FaultStat & countStat() {return _count;} }; -#if !FULL_SYSTEM -//class PageTableFault : public MipsFault -//{ -//private: -// Addr vaddr; -// static FaultName _name; -// static FaultVect _vect; -// static FaultStat _count; -//public: -// PageTableFault(Addr va) -// : vaddr(va) {} -// FaultName name() {return _name;} -// FaultVect vect() {return _vect;} -// FaultStat & countStat() {return _count;} -// void invoke(ThreadContext * tc); -//}; - -static inline Fault genPageTableFault(Addr va) -{ - return new PageTableFault(va); -} -#endif - - static inline Fault genMachineCheckFault() { return new MachineCheckFault; } -static inline Fault genAlignmentFault() -{ - return new AlignmentFault; -} - class ResetFault : public MipsFault { private: diff --git a/src/arch/mips/tlb.cc b/src/arch/mips/tlb.cc new file mode 100644 index 000000000..71111b843 --- /dev/null +++ b/src/arch/mips/tlb.cc @@ -0,0 +1,61 @@ +/* + * 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. + * + * Authors: Gabe Black + */ + +#include <cstring> + +#include "arch/mips/tlb.hh" +#include "params/MipsDTB.hh" +#include "params/MipsITB.hh" + +namespace MipsISA { + void + TlbEntry::serialize(std::ostream &os) + { + SERIALIZE_SCALAR(pageStart); + } + + void + TlbEntry::unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(pageStart); + } +}; + +MipsISA::ITB * +MipsITBParams::create() +{ + return new MipsISA::ITB(name); +} + +MipsISA::DTB * +MipsDTBParams::create() +{ + return new MipsISA::DTB(name); +} diff --git a/src/arch/mips/tlb.hh b/src/arch/mips/tlb.hh new file mode 100644 index 000000000..6025de4c0 --- /dev/null +++ b/src/arch/mips/tlb.hh @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2006 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. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_MIPS_TLB_HH__ +#define __ARCH_MIPS_TLB_HH__ + +#include "sim/tlb.hh" + +namespace MipsISA +{ + struct TlbEntry + { + Addr pageStart; + TlbEntry() {} + TlbEntry(Addr paddr) : pageStart(paddr) {} + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + }; + + class ITB : public GenericITB<> + { + public: + ITB(const std::string &name) : GenericITB<>(name) + {} + }; + + class DTB : public GenericDTB<> + { + public: + DTB(const std::string &name) : GenericDTB<>(name) + {} + }; +}; + +#endif // __ARCH_MIPS_TLB_HH__ diff --git a/src/arch/mips/types.hh b/src/arch/mips/types.hh index fc45ea253..9d2c6285d 100644 --- a/src/arch/mips/types.hh +++ b/src/arch/mips/types.hh @@ -93,7 +93,7 @@ namespace MipsISA RND_DOWN, RND_UP, RND_NEAREST - }; + }; } // namespace MipsISA diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index 0552c282b..81e96a8d6 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -37,18 +37,19 @@ if env['TARGET_ISA'] == 'sparc': Source('floatregfile.cc') Source('intregfile.cc') Source('miscregfile.cc') + Source('pagetable.cc') Source('regfile.cc') Source('remote_gdb.cc') + Source('tlb.cc') Source('utility.cc') + SimObject('SparcTLB.py') + if env['FULL_SYSTEM']: SimObject('SparcSystem.py') - SimObject('SparcTLB.py') - Source('pagetable.cc') Source('stacktrace.cc') Source('system.cc') - Source('tlb.cc') Source('ua2005.cc') Source('vtophys.cc') else: diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 88c086090..07d332b58 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -620,6 +620,70 @@ void PowerOnReset::invoke(ThreadContext * tc) #else // !FULL_SYSTEM +void FastInstructionAccessMMUMiss::invoke(ThreadContext *tc) +{ + Process *p = tc->getProcessPtr(); + Addr paddr; + bool success = p->pTable->translate(vaddr, paddr); + if(!success) { + panic("Tried to execute unmapped address %#x.\n", vaddr); + } else { + + uint64_t entry = 0; + entry |= 0ULL << 1; // Not writable + entry |= 0ULL << 2; // Available in nonpriveleged mode + entry |= 0ULL << 3; // No side effects + entry |= 1ULL << 4; // Virtually cachable + entry |= 1ULL << 5; // Physically cachable + entry |= 0ULL << 6; // Not locked + entry |= mbits(paddr, 39, 13); // Physical address + entry |= 0ULL << 48; // size = 8k + entry |= 0uLL << 59; // Endianness not inverted + entry |= 0ULL << 60; // Not no fault only + entry |= 0ULL << 61; // size = 8k + entry |= 1ULL << 63; // valid + PageTableEntry PTE(entry); + + Addr alignedVaddr = p->pTable->pageAlign(vaddr); + tc->getITBPtr()->insert(alignedVaddr, 0 /*partition id*/, + p->M5_pid /*context id*/, false, PTE); + } +} + +void FastDataAccessMMUMiss::invoke(ThreadContext *tc) +{ + Process *p = tc->getProcessPtr(); + Addr paddr; + bool success = p->pTable->translate(vaddr, paddr); + if(!success) { + p->checkAndAllocNextPage(vaddr); + success = p->pTable->translate(vaddr, paddr); + } + if(!success) { + panic("Tried to access unmapped address %#x.\n", vaddr); + } else { + + uint64_t entry = 0; + entry |= 1ULL << 1; // Writable + entry |= 0ULL << 2; // Available in nonpriveleged mode + entry |= 0ULL << 3; // No side effects + entry |= 1ULL << 4; // Virtually cachable + entry |= 1ULL << 5; // Physically cachable + entry |= 0ULL << 6; // Not locked + entry |= mbits(paddr, 39, 13); // Physical address + entry |= 0ULL << 48; // size = 8k + entry |= 0uLL << 59; // Endianness not inverted + entry |= 0ULL << 60; // Not no fault only + entry |= 0ULL << 61; // size = 8k + entry |= 1ULL << 63; // valid + PageTableEntry PTE(entry); + + Addr alignedVaddr = p->pTable->pageAlign(vaddr); + tc->getDTBPtr()->insert(alignedVaddr, 0 /*partition id*/, + p->M5_pid /*context id*/, false, PTE); + } +} + void SpillNNormal::invoke(ThreadContext *tc) { doNormalFault(tc, trapType(), false); diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh index 2456ad28a..20dd113c6 100644 --- a/src/arch/sparc/faults.hh +++ b/src/arch/sparc/faults.hh @@ -32,6 +32,7 @@ #ifndef __SPARC_FAULTS_HH__ #define __SPARC_FAULTS_HH__ +#include "config/full_system.hh" #include "sim/faults.hh" // The design of the "name" and "vect" functions is in sim/faults.hh @@ -42,6 +43,8 @@ namespace SparcISA typedef uint32_t TrapType; typedef uint32_t FaultPriority; +class ITB; + class SparcFaultBase : public FaultBase { public: @@ -199,9 +202,29 @@ class PAWatchpoint : public SparcFault<PAWatchpoint> {}; class VAWatchpoint : public SparcFault<VAWatchpoint> {}; class FastInstructionAccessMMUMiss : - public SparcFault<FastInstructionAccessMMUMiss> {}; + public SparcFault<FastInstructionAccessMMUMiss> +{ +#if !FULL_SYSTEM + protected: + Addr vaddr; + public: + FastInstructionAccessMMUMiss(Addr addr) : vaddr(addr) + {} + void invoke(ThreadContext * tc); +#endif +}; -class FastDataAccessMMUMiss : public SparcFault<FastDataAccessMMUMiss> {}; +class FastDataAccessMMUMiss : public SparcFault<FastDataAccessMMUMiss> +{ +#if !FULL_SYSTEM + protected: + Addr vaddr; + public: + FastDataAccessMMUMiss(Addr addr) : vaddr(addr) + {} + void invoke(ThreadContext * tc); +#endif +}; class FastDataAccessProtection : public SparcFault<FastDataAccessProtection> {}; @@ -260,11 +283,6 @@ static inline Fault genMachineCheckFault() return new InternalProcessorError; } -static inline Fault genAlignmentFault() -{ - return new MemAddressNotAligned; -} - } // SparcISA namespace diff --git a/src/arch/sparc/handlers.hh b/src/arch/sparc/handlers.hh index ce5b69427..6a866c859 100644 --- a/src/arch/sparc/handlers.hh +++ b/src/arch/sparc/handlers.hh @@ -44,7 +44,7 @@ const int numSpillInsts = 32; const MachInst fillHandler64[numFillInsts] = { - htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0x87802016), //wr %g0, ASI_AIUP, %asi htog(0xe0dba7ff), //ldxa [%sp + BIAS + (0*8)] %asi, %l0 htog(0xe2dba807), //ldxa [%sp + BIAS + (1*8)] %asi, %l1 htog(0xe4dba80f), //ldxa [%sp + BIAS + (2*8)] %asi, %l2 @@ -80,7 +80,7 @@ const MachInst fillHandler64[numFillInsts] = const MachInst fillHandler32[numFillInsts] = { - htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0x87802016), //wr %g0, ASI_AIUP, %asi htog(0xe083a000), //lduwa [%sp + (0*4)] %asi, %l0 htog(0xe283a004), //lduwa [%sp + (1*4)] %asi, %l1 htog(0xe483a008), //lduwa [%sp + (2*4)] %asi, %l2 @@ -116,7 +116,7 @@ const MachInst fillHandler32[numFillInsts] = const MachInst spillHandler64[numSpillInsts] = { - htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0x87802016), //wr %g0, ASI_AIUP, %asi htog(0xe0f3a7ff), //stxa %l0, [%sp + BIAS + (0*8)] %asi htog(0xe2f3a807), //stxa %l1, [%sp + BIAS + (1*8)] %asi htog(0xe4f3a80f), //stxa %l2, [%sp + BIAS + (2*8)] %asi @@ -152,7 +152,7 @@ const MachInst spillHandler64[numSpillInsts] = const MachInst spillHandler32[numSpillInsts] = { - htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0x87802016), //wr %g0, ASI_AIUP, %asi htog(0xe0a3a000), //stwa %l0, [%sp + (0*4)] %asi htog(0xe2a3a004), //stwa %l1, [%sp + (1*4)] %asi htog(0xe4a3a008), //stwa %l2, [%sp + (2*4)] %asi diff --git a/src/arch/sparc/isa/formats/nop.isa b/src/arch/sparc/isa/formats/nop.isa index de2ba2f54..63c541288 100644 --- a/src/arch/sparc/isa/formats/nop.isa +++ b/src/arch/sparc/isa/formats/nop.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -53,6 +53,7 @@ output header {{ Nop(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass) { + flags[IsNop] = true; } // All Nop instructions do the same thing, so this can be diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 0edbdec4b..4f3d20606 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -98,12 +98,6 @@ namespace SparcISA StaticInstPtr decodeInst(ExtMachInst); -#if FULL_SYSTEM - // I don't know what it's for, so I don't - // know what SPARC's value should be - // For loading... XXX This maybe could be USegEnd?? --ali - const Addr LoadAddrMask = ULL(0xffffffffff); - /////////// TLB Stuff //////////// const Addr StartVAddrHole = ULL(0x0000800000000000); const Addr EndVAddrHole = ULL(0xFFFF7FFFFFFFFFFF); @@ -111,6 +105,12 @@ namespace SparcISA const Addr PAddrImplMask = ULL(0x000000FFFFFFFFFF); const Addr BytesInPageMask = ULL(0x1FFF); +#if FULL_SYSTEM + // I don't know what it's for, so I don't + // know what SPARC's value should be + // For loading... XXX This maybe could be USegEnd?? --ali + const Addr LoadAddrMask = ULL(0xffffffffff); + enum InterruptTypes { IT_TRAP_LEVEL_ZERO, diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 0300694cc..7b9c73433 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -54,11 +54,7 @@ string SparcISA::getMiscRegName(RegIndex index) "wstate",*/ "gl", "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", "hstick_cmpr", - "fsr", "prictx", "secctx", "partId", "lsuCtrlReg", "itbTsbC0Ps0", - "itbTsbC0Ps1", "iTlbC0Cnfg", "itbTsbCXPs0", "itbTsbCXPs1", - "iTlbCXCnfg","iTlbSfsr", "iTlbTagAcs", "dtbTsbC0Ps0", - "dtbTsbC0Ps1", "dTlbC0Cnfg", "dtbTsbCXPs0", "dtbTsbCXPs1", - "dTlbCXCnfg","dTlbSfsr", "dTlbSfar", "dTlbTagAcs", + "fsr", "prictx", "secctx", "partId", "lsuCtrlReg", "scratch0", "scratch1", "scratch2", "scratch3", "scratch4", "scratch5", "scratch6", "scratch7", "cpuMondoHead", "cpuMondoTail", "devMondoHead", "devMondoTail", "resErrorHead", "resErrorTail", @@ -113,25 +109,6 @@ void MiscRegFile::clear() partId = 0; lsuCtrlReg = 0; - iTlbC0TsbPs0 = 0; - iTlbC0TsbPs1 = 0; - iTlbC0Config = 0; - iTlbCXTsbPs0 = 0; - iTlbCXTsbPs1 = 0; - iTlbCXConfig = 0; - iTlbSfsr = 0; - iTlbTagAccess = 0; - - dTlbC0TsbPs0 = 0; - dTlbC0TsbPs1 = 0; - dTlbC0Config = 0; - dTlbCXTsbPs0 = 0; - dTlbCXTsbPs1 = 0; - dTlbCXConfig = 0; - dTlbSfsr = 0; - dTlbSfar = 0; - dTlbTagAccess = 0; - memset(scratchPad, 0, sizeof(scratchPad)); #if FULL_SYSTEM tickCompare = NULL; @@ -262,42 +239,6 @@ MiscReg MiscRegFile::readRegNoEffect(int miscReg) case MISCREG_MMU_LSU_CTRL: return lsuCtrlReg; - case MISCREG_MMU_ITLB_C0_TSB_PS0: - return iTlbC0TsbPs0; - case MISCREG_MMU_ITLB_C0_TSB_PS1: - return iTlbC0TsbPs1; - case MISCREG_MMU_ITLB_C0_CONFIG: - return iTlbC0Config; - case MISCREG_MMU_ITLB_CX_TSB_PS0: - return iTlbCXTsbPs0; - case MISCREG_MMU_ITLB_CX_TSB_PS1: - return iTlbCXTsbPs1; - case MISCREG_MMU_ITLB_CX_CONFIG: - return iTlbCXConfig; - case MISCREG_MMU_ITLB_SFSR: - return iTlbSfsr; - case MISCREG_MMU_ITLB_TAG_ACCESS: - return iTlbTagAccess; - - case MISCREG_MMU_DTLB_C0_TSB_PS0: - return dTlbC0TsbPs0; - case MISCREG_MMU_DTLB_C0_TSB_PS1: - return dTlbC0TsbPs1; - case MISCREG_MMU_DTLB_C0_CONFIG: - return dTlbC0Config; - case MISCREG_MMU_DTLB_CX_TSB_PS0: - return dTlbCXTsbPs0; - case MISCREG_MMU_DTLB_CX_TSB_PS1: - return dTlbCXTsbPs1; - case MISCREG_MMU_DTLB_CX_CONFIG: - return dTlbCXConfig; - case MISCREG_MMU_DTLB_SFSR: - return dTlbSfsr; - case MISCREG_MMU_DTLB_SFAR: - return dTlbSfar; - case MISCREG_MMU_DTLB_TAG_ACCESS: - return dTlbTagAccess; - case MISCREG_SCRATCHPAD_R0: return scratchPad[0]; case MISCREG_SCRATCHPAD_R1: @@ -519,59 +460,6 @@ void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val) lsuCtrlReg = val; break; - case MISCREG_MMU_ITLB_C0_TSB_PS0: - iTlbC0TsbPs0 = val; - break; - case MISCREG_MMU_ITLB_C0_TSB_PS1: - iTlbC0TsbPs1 = val; - break; - case MISCREG_MMU_ITLB_C0_CONFIG: - iTlbC0Config = val; - break; - case MISCREG_MMU_ITLB_CX_TSB_PS0: - iTlbCXTsbPs0 = val; - break; - case MISCREG_MMU_ITLB_CX_TSB_PS1: - iTlbCXTsbPs1 = val; - break; - case MISCREG_MMU_ITLB_CX_CONFIG: - iTlbCXConfig = val; - break; - case MISCREG_MMU_ITLB_SFSR: - iTlbSfsr = val; - break; - case MISCREG_MMU_ITLB_TAG_ACCESS: - iTlbTagAccess = val; - break; - - case MISCREG_MMU_DTLB_C0_TSB_PS0: - dTlbC0TsbPs0 = val; - break; - case MISCREG_MMU_DTLB_C0_TSB_PS1: - dTlbC0TsbPs1 = val; - break; - case MISCREG_MMU_DTLB_C0_CONFIG: - dTlbC0Config = val; - break; - case MISCREG_MMU_DTLB_CX_TSB_PS0: - dTlbCXTsbPs0 = val; - break; - case MISCREG_MMU_DTLB_CX_TSB_PS1: - dTlbCXTsbPs1 = val; - break; - case MISCREG_MMU_DTLB_CX_CONFIG: - dTlbCXConfig = val; - break; - case MISCREG_MMU_DTLB_SFSR: - dTlbSfsr = val; - break; - case MISCREG_MMU_DTLB_SFAR: - dTlbSfar = val; - break; - case MISCREG_MMU_DTLB_TAG_ACCESS: - dTlbTagAccess = val; - break; - case MISCREG_SCRATCHPAD_R0: scratchPad[0] = val; break; @@ -733,23 +621,6 @@ void MiscRegFile::serialize(std::ostream & os) SERIALIZE_SCALAR(secContext); SERIALIZE_SCALAR(partId); SERIALIZE_SCALAR(lsuCtrlReg); - SERIALIZE_SCALAR(iTlbC0TsbPs0); - SERIALIZE_SCALAR(iTlbC0TsbPs1); - SERIALIZE_SCALAR(iTlbC0Config); - SERIALIZE_SCALAR(iTlbCXTsbPs0); - SERIALIZE_SCALAR(iTlbCXTsbPs1); - SERIALIZE_SCALAR(iTlbCXConfig); - SERIALIZE_SCALAR(iTlbSfsr); - SERIALIZE_SCALAR(iTlbTagAccess); - SERIALIZE_SCALAR(dTlbC0TsbPs0); - SERIALIZE_SCALAR(dTlbC0TsbPs1); - SERIALIZE_SCALAR(dTlbC0Config); - SERIALIZE_SCALAR(dTlbCXTsbPs0); - SERIALIZE_SCALAR(dTlbCXTsbPs1); - SERIALIZE_SCALAR(dTlbCXConfig); - SERIALIZE_SCALAR(dTlbSfsr); - SERIALIZE_SCALAR(dTlbSfar); - SERIALIZE_SCALAR(dTlbTagAccess); SERIALIZE_ARRAY(scratchPad,8); SERIALIZE_SCALAR(cpu_mondo_head); SERIALIZE_SCALAR(cpu_mondo_tail); @@ -827,23 +698,6 @@ void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) UNSERIALIZE_SCALAR(secContext); UNSERIALIZE_SCALAR(partId); UNSERIALIZE_SCALAR(lsuCtrlReg); - UNSERIALIZE_SCALAR(iTlbC0TsbPs0); - UNSERIALIZE_SCALAR(iTlbC0TsbPs1); - UNSERIALIZE_SCALAR(iTlbC0Config); - UNSERIALIZE_SCALAR(iTlbCXTsbPs0); - UNSERIALIZE_SCALAR(iTlbCXTsbPs1); - UNSERIALIZE_SCALAR(iTlbCXConfig); - UNSERIALIZE_SCALAR(iTlbSfsr); - UNSERIALIZE_SCALAR(iTlbTagAccess); - UNSERIALIZE_SCALAR(dTlbC0TsbPs0); - UNSERIALIZE_SCALAR(dTlbC0TsbPs1); - UNSERIALIZE_SCALAR(dTlbC0Config); - UNSERIALIZE_SCALAR(dTlbCXTsbPs0); - UNSERIALIZE_SCALAR(dTlbCXTsbPs1); - UNSERIALIZE_SCALAR(dTlbCXConfig); - UNSERIALIZE_SCALAR(dTlbSfsr); - UNSERIALIZE_SCALAR(dTlbSfar); - UNSERIALIZE_SCALAR(dTlbTagAccess); UNSERIALIZE_ARRAY(scratchPad,8); UNSERIALIZE_SCALAR(cpu_mondo_head); UNSERIALIZE_SCALAR(cpu_mondo_tail); diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 867f959e1..3e17779a9 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -100,25 +100,6 @@ namespace SparcISA MISCREG_MMU_PART_ID, MISCREG_MMU_LSU_CTRL, - MISCREG_MMU_ITLB_C0_TSB_PS0, - MISCREG_MMU_ITLB_C0_TSB_PS1, - MISCREG_MMU_ITLB_C0_CONFIG, - MISCREG_MMU_ITLB_CX_TSB_PS0, - MISCREG_MMU_ITLB_CX_TSB_PS1, - MISCREG_MMU_ITLB_CX_CONFIG, - MISCREG_MMU_ITLB_SFSR, - MISCREG_MMU_ITLB_TAG_ACCESS, /* 50 */ - - MISCREG_MMU_DTLB_C0_TSB_PS0, - MISCREG_MMU_DTLB_C0_TSB_PS1, - MISCREG_MMU_DTLB_C0_CONFIG, - MISCREG_MMU_DTLB_CX_TSB_PS0, - MISCREG_MMU_DTLB_CX_TSB_PS1, - MISCREG_MMU_DTLB_CX_CONFIG, - MISCREG_MMU_DTLB_SFSR, - MISCREG_MMU_DTLB_SFAR, - MISCREG_MMU_DTLB_TAG_ACCESS, - /** Scratchpad regiscers **/ MISCREG_SCRATCHPAD_R0, /* 60 */ MISCREG_SCRATCHPAD_R1, @@ -241,25 +222,6 @@ namespace SparcISA uint16_t partId; uint64_t lsuCtrlReg; - uint64_t iTlbC0TsbPs0; - uint64_t iTlbC0TsbPs1; - uint64_t iTlbC0Config; - uint64_t iTlbCXTsbPs0; - uint64_t iTlbCXTsbPs1; - uint64_t iTlbCXConfig; - uint64_t iTlbSfsr; - uint64_t iTlbTagAccess; - - uint64_t dTlbC0TsbPs0; - uint64_t dTlbC0TsbPs1; - uint64_t dTlbC0Config; - uint64_t dTlbCXTsbPs0; - uint64_t dTlbCXTsbPs1; - uint64_t dTlbCXConfig; - uint64_t dTlbSfsr; - uint64_t dTlbSfar; - uint64_t dTlbTagAccess; - uint64_t scratchPad[8]; uint64_t cpu_mondo_head; diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh index 980225052..961870579 100644 --- a/src/arch/sparc/pagetable.hh +++ b/src/arch/sparc/pagetable.hh @@ -190,6 +190,11 @@ struct TlbRange { struct TlbEntry { + Addr pageStart; + TlbEntry() + {} + TlbEntry(Addr addr) : pageStart(addr) + {} TlbRange range; PageTableEntry pte; bool used; diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 41a1c2136..29b1a244b 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -121,6 +121,12 @@ Sparc32LiveProcess::startup() threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0); //Set the ASI register to something fixed threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); + + /* + * T1 specific registers + */ + //Turn on the icache, dcache, dtb translation, and itb translation. + threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15); } void @@ -137,7 +143,7 @@ Sparc64LiveProcess::startup() threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0); threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0); - // + /* * Register window management registers */ @@ -163,6 +169,12 @@ Sparc64LiveProcess::startup() threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0); //Set the ASI register to something fixed threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); + + /* + * T1 specific registers + */ + //Turn on the icache, dcache, dtb translation, and itb translation. + threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15); } M5_32_auxv_t::M5_32_auxv_t(int32_t type, int32_t val) diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 667b1f002..d6be52424 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -326,42 +326,6 @@ void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) dest->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, src->readMiscRegNoEffect(MISCREG_MMU_LSU_CTRL)); - dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, - src->readMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); - dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, - src->readMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); - dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_C0_CONFIG, - src->readMiscRegNoEffect(MISCREG_MMU_ITLB_C0_CONFIG)); - dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, - src->readMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); - dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, - src->readMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); - dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_CX_CONFIG, - src->readMiscRegNoEffect(MISCREG_MMU_ITLB_CX_CONFIG)); - dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_SFSR, - src->readMiscRegNoEffect(MISCREG_MMU_ITLB_SFSR)); - dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_TAG_ACCESS, - src->readMiscRegNoEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); - - dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, - src->readMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); - dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, - src->readMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); - dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_C0_CONFIG, - src->readMiscRegNoEffect(MISCREG_MMU_DTLB_C0_CONFIG)); - dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, - src->readMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); - dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, - src->readMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); - dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_CX_CONFIG, - src->readMiscRegNoEffect(MISCREG_MMU_DTLB_CX_CONFIG)); - dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_SFSR, - src->readMiscRegNoEffect(MISCREG_MMU_DTLB_SFSR)); - dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_SFAR, - src->readMiscRegNoEffect(MISCREG_MMU_DTLB_SFAR)); - dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_TAG_ACCESS, - src->readMiscRegNoEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); - // Scratchpad Registers dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R0, src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R0)); diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 21d56b8c6..edc9d37a9 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -60,6 +60,15 @@ TLB::TLB(const std::string &name, int s) for (int x = 0; x < size; x++) freeList.push_back(&tlb[x]); + + c0_tsb_ps0 = 0; + c0_tsb_ps1 = 0; + c0_config = 0; + cx_tsb_ps0 = 0; + cx_tsb_ps1 = 0; + cx_config = 0; + sfsr = 0; + tag_access = 0; } void @@ -393,12 +402,8 @@ TLB::validVirtualAddress(Addr va, bool am) } void -TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, - bool se, FaultTypes ft, int asi) +TLB::writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi) { - uint64_t sfsr; - sfsr = tc->readMiscRegNoEffect(reg); - if (sfsr & 0x1) sfsr = 0x3; else @@ -411,51 +416,35 @@ TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, sfsr |= 1 << 6; sfsr |= ft << 7; sfsr |= asi << 16; - tc->setMiscReg(reg, sfsr); } void -TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context) +TLB::writeTagAccess(Addr va, int context) { DPRINTF(TLB, "TLB: Writing Tag Access: va: %#X ctx: %#X value: %#X\n", va, context, mbits(va, 63,13) | mbits(context,12,0)); - tc->setMiscReg(reg, mbits(va, 63,13) | mbits(context,12,0)); + tag_access = mbits(va, 63,13) | mbits(context,12,0); } void -ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct, - bool se, FaultTypes ft, int asi) +ITB::writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi) { DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n", (int)write, ct, ft, asi); - TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi); + TLB::writeSfsr(write, ct, se, ft, asi); } void -ITB::writeTagAccess(ThreadContext *tc, Addr va, int context) -{ - TLB::writeTagAccess(tc, MISCREG_MMU_ITLB_TAG_ACCESS, va, context); -} - -void -DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, +DTB::writeSfsr(Addr a, bool write, ContextType ct, bool se, FaultTypes ft, int asi) { DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", a, (int)write, ct, ft, asi); - TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); - tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a); -} - -void -DTB::writeTagAccess(ThreadContext *tc, Addr va, int context) -{ - TLB::writeTagAccess(tc, MISCREG_MMU_DTLB_TAG_ACCESS, va, context); + TLB::writeSfsr(write, ct, se, ft, asi); + sfar = a; } - - Fault ITB::translate(RequestPtr &req, ThreadContext *tc) { @@ -521,7 +510,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) // If the access is unaligned trap if (vaddr & 0x3) { - writeSfsr(tc, false, ct, false, OtherFault, asi); + writeSfsr(false, ct, false, OtherFault, asi); return new MemAddressNotAligned; } @@ -529,7 +518,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) vaddr = vaddr & VAddrAMask; if (!validVirtualAddress(vaddr, addr_mask)) { - writeSfsr(tc, false, ct, false, VaOutOfRange, asi); + writeSfsr(false, ct, false, VaOutOfRange, asi); return new InstructionAccessException; } @@ -542,17 +531,21 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) } if (e == NULL || !e->valid) { - writeTagAccess(tc, vaddr, context); + writeTagAccess(vaddr, context); if (real) return new InstructionRealTranslationMiss; else +#if FULL_SYSTEM return new FastInstructionAccessMMUMiss; +#else + return new FastInstructionAccessMMUMiss(req->getVaddr()); +#endif } // were not priviledged accesing priv page if (!priv && e->pte.priv()) { - writeTagAccess(tc, vaddr, context); - writeSfsr(tc, false, ct, false, PrivViolation, asi); + writeTagAccess(vaddr, context); + writeSfsr(false, ct, false, PrivViolation, asi); return new InstructionAccessException; } @@ -580,6 +573,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) asi = (ASI)req->getAsi(); bool implicit = false; bool hpriv = bits(tlbdata,0,0); + bool unaligned = (vaddr & size-1); DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", vaddr, size, asi); @@ -590,43 +584,47 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (asi == ASI_IMPLICIT) implicit = true; - if (hpriv && implicit) { - req->setPaddr(vaddr & PAddrImplMask); - return NoFault; - } - - // Be fast if we can! - if (cacheValid && cacheState == tlbdata) { - - + // Only use the fast path here if there doesn't need to be an unaligned + // trap later + if (!unaligned) { + if (hpriv && implicit) { + req->setPaddr(vaddr & PAddrImplMask); + return NoFault; + } - if (cacheEntry[0]) { - TlbEntry *ce = cacheEntry[0]; - Addr ce_va = ce->range.va; - if (cacheAsi[0] == asi && - ce_va < vaddr + size && ce_va + ce->range.size > vaddr && - (!write || ce->pte.writable())) { - req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); - if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) - req->setFlags(req->getFlags() | UNCACHEABLE); - DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); - return NoFault; - } // if matched - } // if cache entry valid - if (cacheEntry[1]) { - TlbEntry *ce = cacheEntry[1]; - Addr ce_va = ce->range.va; - if (cacheAsi[1] == asi && - ce_va < vaddr + size && ce_va + ce->range.size > vaddr && - (!write || ce->pte.writable())) { - req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); - if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) - req->setFlags(req->getFlags() | UNCACHEABLE); - DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); - return NoFault; - } // if matched - } // if cache entry valid - } + // Be fast if we can! + if (cacheValid && cacheState == tlbdata) { + + + + if (cacheEntry[0]) { + TlbEntry *ce = cacheEntry[0]; + Addr ce_va = ce->range.va; + if (cacheAsi[0] == asi && + ce_va < vaddr + size && ce_va + ce->range.size > vaddr && + (!write || ce->pte.writable())) { + req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); + if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) + req->setFlags(req->getFlags() | UNCACHEABLE); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); + return NoFault; + } // if matched + } // if cache entry valid + if (cacheEntry[1]) { + TlbEntry *ce = cacheEntry[1]; + Addr ce_va = ce->range.va; + if (cacheAsi[1] == asi && + ce_va < vaddr + size && ce_va + ce->range.size > vaddr && + (!write || ce->pte.writable())) { + req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); + if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) + req->setFlags(req->getFlags() | UNCACHEABLE); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); + return NoFault; + } // if matched + } // if cache entry valid + } + } bool red = bits(tlbdata,1,1); bool priv = bits(tlbdata,2,2); @@ -661,12 +659,12 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) // We need to check for priv level/asi priv if (!priv && !hpriv && !AsiIsUnPriv(asi)) { // It appears that context should be Nucleus in these cases? - writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); + writeSfsr(vaddr, write, Nucleus, false, IllegalAsi, asi); return new PrivilegedAction; } if (!hpriv && AsiIsHPriv(asi)) { - writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); + writeSfsr(vaddr, write, Nucleus, false, IllegalAsi, asi); return new DataAccessException; } @@ -688,8 +686,12 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (!implicit && asi != ASI_P && asi != ASI_S) { if (AsiIsLittle(asi)) panic("Little Endian ASIs not supported\n"); - if (AsiIsNoFault(asi)) - panic("No Fault ASIs not supported\n"); + + //XXX It's unclear from looking at the documentation how a no fault + //load differs from a regular one, other than what happens concerning + //nfo and e bits in the TTE +// if (AsiIsNoFault(asi)) +// panic("No Fault ASIs not supported\n"); if (AsiIsPartialStore(asi)) panic("Partial Store ASIs not supported\n"); @@ -709,13 +711,13 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) goto handleSparcErrorRegAccess; if (!AsiIsReal(asi) && !AsiIsNucleus(asi) && !AsiIsAsIfUser(asi) && - !AsiIsTwin(asi) && !AsiIsBlock(asi)) + !AsiIsTwin(asi) && !AsiIsBlock(asi) && !AsiIsNoFault(asi)) panic("Accessing ASI %#X. Should we?\n", asi); } // If the asi is unaligned trap - if (vaddr & size-1) { - writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); + if (unaligned) { + writeSfsr(vaddr, false, ct, false, OtherFault, asi); return new MemAddressNotAligned; } @@ -723,7 +725,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) vaddr = vaddr & VAddrAMask; if (!validVirtualAddress(vaddr, addr_mask)) { - writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi); + writeSfsr(vaddr, false, ct, true, VaOutOfRange, asi); return new DataAccessException; } @@ -741,36 +743,40 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) e = lookup(vaddr, part_id, real, context); if (e == NULL || !e->valid) { - writeTagAccess(tc, vaddr, context); + writeTagAccess(vaddr, context); DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n"); if (real) return new DataRealTranslationMiss; else +#if FULL_SYSTEM return new FastDataAccessMMUMiss; +#else + return new FastDataAccessMMUMiss(req->getVaddr()); +#endif } if (!priv && e->pte.priv()) { - writeTagAccess(tc, vaddr, context); - writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); + writeTagAccess(vaddr, context); + writeSfsr(vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); return new DataAccessException; } if (write && !e->pte.writable()) { - writeTagAccess(tc, vaddr, context); - writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); + writeTagAccess(vaddr, context); + writeSfsr(vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); return new FastDataAccessProtection; } if (e->pte.nofault() && !AsiIsNoFault(asi)) { - writeTagAccess(tc, vaddr, context); - writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); + writeTagAccess(vaddr, context); + writeSfsr(vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); return new DataAccessException; } if (e->pte.sideffect() && AsiIsNoFault(asi)) { - writeTagAccess(tc, vaddr, context); - writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), SideEffect, asi); + writeTagAccess(vaddr, context); + writeSfsr(vaddr, write, ct, e->pte.sideffect(), SideEffect, asi); return new DataAccessException; } @@ -802,7 +808,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) /** Normal flow ends here. */ handleIntRegAccess: if (!hpriv) { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi); if (priv) return new DataAccessException; else @@ -811,7 +817,7 @@ handleIntRegAccess: if (asi == ASI_SWVR_UDB_INTR_W && !write || asi == ASI_SWVR_UDB_INTR_R && write) { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi); return new DataAccessException; } @@ -820,25 +826,25 @@ handleIntRegAccess: handleScratchRegAccess: if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi); return new DataAccessException; } goto regAccessOk; handleQueueRegAccess: if (!priv && !hpriv) { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi); return new PrivilegedAction; } if (!hpriv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi); return new DataAccessException; } goto regAccessOk; handleSparcErrorRegAccess: if (!hpriv) { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi); if (priv) return new DataAccessException; else @@ -855,6 +861,8 @@ handleMmuRegAccess: return NoFault; }; +#if FULL_SYSTEM + Tick DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) { @@ -865,6 +873,8 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", (uint32_t)pkt->req->getAsi(), pkt->getAddr()); + ITB * itb = tc->getITBPtr(); + switch (asi) { case ASI_LSU_CONTROL_REG: assert(va == 0); @@ -888,51 +898,51 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0)); + pkt->set(c0_tsb_ps0); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1)); + pkt->set(c0_tsb_ps1); break; case ASI_DMMU_CTXT_ZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG)); + pkt->set(c0_config); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0)); + pkt->set(itb->c0_tsb_ps0); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1)); + pkt->set(itb->c0_tsb_ps1); break; case ASI_IMMU_CTXT_ZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG)); + pkt->set(itb->c0_config); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0)); + pkt->set(cx_tsb_ps0); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1)); + pkt->set(cx_tsb_ps1); break; case ASI_DMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); + pkt->set(cx_config); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0)); + pkt->set(itb->cx_tsb_ps0); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1)); + pkt->set(itb->cx_tsb_ps1); break; case ASI_IMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); + pkt->set(itb->cx_config); break; case ASI_SPARC_ERROR_STATUS_REG: pkt->set((uint64_t)0); @@ -944,14 +954,14 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) case ASI_IMMU: switch (va) { case 0x0: - temp = tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS); + temp = itb->tag_access; pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); break; case 0x18: - pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_SFSR)); + pkt->set(itb->sfsr); break; case 0x30: - pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS)); + pkt->set(itb->tag_access); break; default: goto doMmuReadError; @@ -960,17 +970,17 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) case ASI_DMMU: switch (va) { case 0x0: - temp = tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS); + temp = tag_access; pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); break; case 0x18: - pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_SFSR)); + pkt->set(sfsr); break; case 0x20: - pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_SFAR)); + pkt->set(sfar); break; case 0x30: - pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS)); + pkt->set(tag_access); break; case 0x80: pkt->set(tc->readMiscReg(MISCREG_MMU_PART_ID)); @@ -981,35 +991,35 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) break; case ASI_DMMU_TSB_PS0_PTR_REG: pkt->set(MakeTsbPtr(Ps0, - tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS), - tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0), - tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), - tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0), - tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG))); + tag_access, + c0_tsb_ps0, + c0_config, + cx_tsb_ps0, + cx_config)); break; case ASI_DMMU_TSB_PS1_PTR_REG: pkt->set(MakeTsbPtr(Ps1, - tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS), - tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1), - tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), - tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1), - tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG))); + tag_access, + c0_tsb_ps1, + c0_config, + cx_tsb_ps1, + cx_config)); break; case ASI_IMMU_TSB_PS0_PTR_REG: pkt->set(MakeTsbPtr(Ps0, - tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS), - tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0), - tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), - tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0), - tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG))); + itb->tag_access, + itb->c0_tsb_ps0, + itb->c0_config, + itb->cx_tsb_ps0, + itb->cx_config)); break; case ASI_IMMU_TSB_PS1_PTR_REG: pkt->set(MakeTsbPtr(Ps1, - tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS), - tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1), - tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), - tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1), - tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG))); + itb->tag_access, + itb->c0_tsb_ps1, + itb->c0_config, + itb->cx_tsb_ps1, + itb->cx_config)); break; case ASI_SWVR_INTR_RECEIVE: pkt->set(tc->getCpuPtr()->get_interrupts(IT_INT_VEC)); @@ -1049,6 +1059,8 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n", (uint32_t)asi, va, data); + ITB * itb = tc->getITBPtr(); + switch (asi) { case ASI_LSU_CONTROL_REG: assert(va == 0); @@ -1073,51 +1085,51 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0, data); + c0_tsb_ps0 = data; break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1, data); + c0_tsb_ps1 = data; break; case ASI_DMMU_CTXT_ZERO_CONFIG: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_DTLB_C0_CONFIG, data); + c0_config = data; break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0, data); + itb->c0_tsb_ps0 = data; break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1, data); + itb->c0_tsb_ps1 = data; break; case ASI_IMMU_CTXT_ZERO_CONFIG: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_ITLB_C0_CONFIG, data); + itb->c0_config = data; break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0, data); + cx_tsb_ps0 = data; break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1, data); + cx_tsb_ps1 = data; break; case ASI_DMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_DTLB_CX_CONFIG, data); + cx_config = data; break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0, data); + itb->cx_tsb_ps0 = data; break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1, data); + itb->cx_tsb_ps1 = data; break; case ASI_IMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - tc->setMiscReg(MISCREG_MMU_ITLB_CX_CONFIG, data); + itb->cx_config = data; break; case ASI_SPARC_ERROR_EN_REG: case ASI_SPARC_ERROR_STATUS_REG: @@ -1130,11 +1142,11 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) case ASI_IMMU: switch (va) { case 0x18: - tc->setMiscReg(MISCREG_MMU_ITLB_SFSR, data); + itb->sfsr = data; break; case 0x30: sext<59>(bits(data, 59,0)); - tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, data); + itb->tag_access = data; break; default: goto doMmuWriteError; @@ -1144,7 +1156,7 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) entry_insert = bits(va, 8,3); case ASI_ITLB_DATA_IN_REG: assert(entry_insert != -1 || mbits(va,10,9) == va); - ta_insert = tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS); + ta_insert = itb->tag_access; va_insert = mbits(ta_insert, 63,13); ct_insert = mbits(ta_insert, 12,0); part_insert = tc->readMiscReg(MISCREG_MMU_PART_ID); @@ -1158,7 +1170,7 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) entry_insert = bits(va, 8,3); case ASI_DTLB_DATA_IN_REG: assert(entry_insert != -1 || mbits(va,10,9) == va); - ta_insert = tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS); + ta_insert = tag_access; va_insert = mbits(ta_insert, 63,13); ct_insert = mbits(ta_insert, 12,0); part_insert = tc->readMiscReg(MISCREG_MMU_PART_ID); @@ -1205,11 +1217,11 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) case ASI_DMMU: switch (va) { case 0x18: - tc->setMiscReg(MISCREG_MMU_DTLB_SFSR, data); + sfsr = data; break; case 0x30: sext<59>(bits(data, 59,0)); - tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, data); + tag_access = data; break; case 0x80: tc->setMiscReg(MISCREG_MMU_PART_ID, data); @@ -1273,30 +1285,33 @@ doMmuWriteError: return tc->getCpuPtr()->cycles(1); } +#endif + void DTB::GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs) { uint64_t tag_access = mbits(addr,63,13) | mbits(ctx,12,0); + ITB * itb = tc->getITBPtr(); ptrs[0] = MakeTsbPtr(Ps0, tag_access, - tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0), - tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), - tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0), - tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); + c0_tsb_ps0, + c0_config, + cx_tsb_ps0, + cx_config); ptrs[1] = MakeTsbPtr(Ps1, tag_access, - tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1), - tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), - tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1), - tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); + c0_tsb_ps1, + c0_config, + cx_tsb_ps1, + cx_config); ptrs[2] = MakeTsbPtr(Ps0, tag_access, - tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0), - tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), - tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0), - tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); + itb->c0_tsb_ps0, + itb->c0_config, + itb->cx_tsb_ps0, + itb->cx_config); ptrs[3] = MakeTsbPtr(Ps1, tag_access, - tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1), - tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), - tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1), - tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); + itb->c0_tsb_ps1, + itb->c0_config, + itb->cx_tsb_ps1, + itb->cx_config); } @@ -1354,6 +1369,15 @@ TLB::serialize(std::ostream &os) nameOut(os, csprintf("%s.PTE%d", name(), x)); tlb[x].serialize(os); } + + SERIALIZE_SCALAR(c0_tsb_ps0); + SERIALIZE_SCALAR(c0_tsb_ps1); + SERIALIZE_SCALAR(c0_config); + SERIALIZE_SCALAR(cx_tsb_ps0); + SERIALIZE_SCALAR(cx_tsb_ps1); + SERIALIZE_SCALAR(cx_config); + SERIALIZE_SCALAR(sfsr); + SERIALIZE_SCALAR(tag_access); } void @@ -1383,6 +1407,29 @@ TLB::unserialize(Checkpoint *cp, const std::string §ion) lookupTable.insert(tlb[x].range, &tlb[x]); } + + UNSERIALIZE_SCALAR(c0_tsb_ps0); + UNSERIALIZE_SCALAR(c0_tsb_ps1); + UNSERIALIZE_SCALAR(c0_config); + UNSERIALIZE_SCALAR(cx_tsb_ps0); + UNSERIALIZE_SCALAR(cx_tsb_ps1); + UNSERIALIZE_SCALAR(cx_config); + UNSERIALIZE_SCALAR(sfsr); + UNSERIALIZE_SCALAR(tag_access); +} + +void +DTB::serialize(std::ostream &os) +{ + TLB::serialize(os); + SERIALIZE_SCALAR(sfar); +} + +void +DTB::unserialize(Checkpoint *cp, const std::string §ion) +{ + TLB::unserialize(cp, section); + UNSERIALIZE_SCALAR(sfar); } /* end namespace SparcISA */ } diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index b5f02c62e..d35a6e096 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -34,6 +34,7 @@ #include "arch/sparc/asi.hh" #include "arch/sparc/tlb_map.hh" #include "base/misc.hh" +#include "config/full_system.hh" #include "mem/request.hh" #include "sim/faults.hh" #include "sim/sim_object.hh" @@ -46,6 +47,23 @@ namespace SparcISA class TLB : public SimObject { +#if !FULL_SYSTEM + //These faults need to be able to populate the tlb in SE mode. + friend class FastInstructionAccessMMUMiss; + friend class FastDataAccessMMUMiss; +#endif + + //TLB state + protected: + uint64_t c0_tsb_ps0; + uint64_t c0_tsb_ps1; + uint64_t c0_config; + uint64_t cx_tsb_ps0; + uint64_t cx_tsb_ps1; + uint64_t cx_config; + uint64_t sfsr; + uint64_t tag_access; + protected: TlbMap lookupTable;; typedef TlbMap::iterator MapIter; @@ -120,13 +138,13 @@ class TLB : public SimObject /** Checks if the virtual address provided is a valid one. */ bool validVirtualAddress(Addr va, bool am); - void writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, + void writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi); void clearUsedBits(); - void writeTagAccess(ThreadContext *tc, int reg, Addr va, int context); + void writeTagAccess(Addr va, int context); public: TLB(const std::string &name, int size); @@ -152,31 +170,39 @@ class ITB : public TLB Fault translate(RequestPtr &req, ThreadContext *tc); private: - void writeSfsr(ThreadContext *tc, bool write, ContextType ct, + void writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi); - void writeTagAccess(ThreadContext *tc, Addr va, int context); TlbEntry *cacheEntry; friend class DTB; }; class DTB : public TLB { + //DTLB specific state + protected: + uint64_t sfar; public: DTB(const std::string &name, int size) : TLB(name, size) { + sfar = 0; cacheEntry[0] = NULL; cacheEntry[1] = NULL; } Fault translate(RequestPtr &req, ThreadContext *tc, bool write); +#if FULL_SYSTEM Tick doMmuRegRead(ThreadContext *tc, Packet *pkt); Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt); +#endif void GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs); + // Checkpointing + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + private: - void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, + void writeSfsr(Addr a, bool write, ContextType ct, bool se, FaultTypes ft, int asi); - void writeTagAccess(ThreadContext *tc, Addr va, int context); uint64_t MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config); diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index e8f8059ce..b791a0624 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -96,6 +96,9 @@ if env['TARGET_ISA'] == 'x86': Source('predecoder_tables.cc') Source('regfile.cc') Source('remote_gdb.cc') + Source('tlb.cc') + + SimObject('X86TLB.py') if env['FULL_SYSTEM']: # Full-system sources diff --git a/src/arch/x86/X86TLB.py b/src/arch/x86/X86TLB.py new file mode 100644 index 000000000..f16408e63 --- /dev/null +++ b/src/arch/x86/X86TLB.py @@ -0,0 +1,75 @@ +# Copyright (c) 2007 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# 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. +# +# Authors: Gabe Black + +from m5.SimObject import SimObject +from m5.params import * +class X86TLB(SimObject): + type = 'X86TLB' + abstract = True + #size = Param.Int("TLB size") + +class X86DTB(X86TLB): + type = 'X86DTB' + cxx_namespace = 'X86ISA' + cxx_class = 'DTB' + + #size = 64 + +class X86ITB(X86TLB): + type = 'X86ITB' + cxx_namespace = 'X86ISA' + cxx_class = 'ITB' + + #size = 64 diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index 51c34cebd..936d0357c 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -91,20 +91,10 @@ namespace X86ISA } }; - static inline Fault genPageTableFault(Addr va) - { - panic("Page table fault not implemented in x86!\n"); - } - static inline Fault genMachineCheckFault() { panic("Machine check fault not implemented in x86!\n"); } - - static inline Fault genAlignmentFault() - { - panic("Alignment fault not implemented (or for the most part existant) in x86!\n"); - } }; #endif // __ARCH_X86_FAULTS_HH__ diff --git a/src/arch/x86/insts/microldstop.hh b/src/arch/x86/insts/microldstop.hh index fac1fa3aa..5b1210d69 100644 --- a/src/arch/x86/insts/microldstop.hh +++ b/src/arch/x86/insts/microldstop.hh @@ -106,29 +106,22 @@ namespace X86ISA Fault read(Context *xc, Addr EA, MemType & Mem, unsigned flags) const { Fault fault = NoFault; - int size = dataSize; - Addr alignedEA = EA & ~(dataSize - 1); - if (EA != alignedEA) - size *= 2; - switch(size) + switch(dataSize) { case 1: - fault = xc->read(alignedEA, (uint8_t&)(Mem.a), flags); + fault = xc->read(EA, (uint8_t&)Mem, flags); break; case 2: - fault = xc->read(alignedEA, (uint16_t&)(Mem.a), flags); + fault = xc->read(EA, (uint16_t&)Mem, flags); break; case 4: - fault = xc->read(alignedEA, (uint32_t&)(Mem.a), flags); + fault = xc->read(EA, (uint32_t&)Mem, flags); break; case 8: - fault = xc->read(alignedEA, (uint64_t&)(Mem.a), flags); - break; - case 16: - fault = xc->read(alignedEA, Mem, flags); + fault = xc->read(EA, (uint64_t&)Mem, flags); break; default: - panic("Bad operand size %d for read at %#x.\n", size, EA); + panic("Bad operand size %d for read at %#x.\n", dataSize, EA); } return fault; } @@ -137,29 +130,22 @@ namespace X86ISA Fault write(Context *xc, MemType & Mem, Addr EA, unsigned flags) const { Fault fault = NoFault; - int size = dataSize; - Addr alignedEA = EA & ~(dataSize - 1); - if (EA != alignedEA) - size *= 2; - switch(size) + switch(dataSize) { case 1: - fault = xc->write((uint8_t&)(Mem.a), alignedEA, flags, 0); + fault = xc->write((uint8_t&)Mem, EA, flags, 0); break; case 2: - fault = xc->write((uint16_t&)(Mem.a), alignedEA, flags, 0); + fault = xc->write((uint16_t&)Mem, EA, flags, 0); break; case 4: - fault = xc->write((uint32_t&)(Mem.a), alignedEA, flags, 0); + fault = xc->write((uint32_t&)Mem, EA, flags, 0); break; case 8: - fault = xc->write((uint64_t&)(Mem.a), alignedEA, flags, 0); - break; - case 16: - fault = xc->write(Mem, alignedEA, flags, 0); + fault = xc->write((uint64_t&)Mem, EA, flags, 0); break; default: - panic("Bad operand size %d for write at %#x.\n", size, EA); + panic("Bad operand size %d for write at %#x.\n", dataSize, EA); } return fault; } diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index ee7fbc683..d8db47063 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -332,8 +332,8 @@ 0x3: mov_Ov_rAX(); 0x4: movs_Yb_Xb(); 0x5: movs_Yv_Xv(); - 0x6: cmps_Yb_Xb(); - 0x7: cmps_Yv_Xv(); + 0x6: StringInst::CMPS(Yb,Xb); + 0x7: StringInst::CMPS(Yv,Xv); } 0x15: decode OPCODE_OP_BOTTOM3 { 0x0: Inst::TEST(rAb,Ib); diff --git a/src/arch/x86/isa/insts/processor_information.py b/src/arch/x86/isa/insts/processor_information.py index 48891cd84..9cad8181c 100644 --- a/src/arch/x86/isa/insts/processor_information.py +++ b/src/arch/x86/isa/insts/processor_information.py @@ -55,15 +55,351 @@ microcode = ''' def macroop CPUID_R { - # - # For now, the CPUID function number will be hard wired to 0x8000_0000. - # Getting it to work more robustly will likely require microcode branching - # which probably doesn't work at the moment. - # +# +# Find which type of cpuid function it is by checking bit 31. Also clear that +# bit to form an offset into the functions of that type. +# + limm t1, 0x80000000, dataSize=4 + and t2, t1, rax, flags=(EZF,) + # clear the bit + xor t1, t2, rax + +# +# Do range checking on the offset +# + # If EZF is set, the function is standard and the max is 0x1. + movi t2, t2, 0x1, flags=(CEZF,) + # If EZF is cleared, the function is extended and the max is 0x18. + movi t2, t2, 0x18, flags=(nCEZF,) + subi t0, t1, t2, flags=(ECF,) + # ECF will be set if the offset is too large. + bri t0, label("end"), flags=(CECF,) + + +# +# Jump to the right portion +# + movi t2, t2, label("standardStart"), flags=(CEZF,) + movi t2, t2, label("extendedStart"), flags=(nCEZF,) + # This gives each function 8 microops to use. It's wasteful because only + # 5 will be needed, but a multiply would be expensive. In the system + # described in the RISC86 patent, the fifth instruction would really be + # the sequencing field on an op quad, so each function would be implemented + # by -exactly- one op quad. Since we're approximating, this should be ok. + slli t1, t1, 3 + br t2, t1 + +############################################################################# +############################################################################# + +# +# Standard functions. +# + +standardStart: + +# 0x00000000 -- Processor Vendor and Largest Standard Function Number + limm rax, 0x00000001, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x00000001 -- Family, Model, Stepping Identifiers + limm rax, 0x00020f51, dataSize=4 + limm rbx, 0x00000405, dataSize=4 + limm rdx, 0xe3d3fbff, dataSize=4 + limm rcx, 0x00000001, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# +# Extended functions. +# + +extendedStart: + +# 0x80000000 -- Processor Vendor and Largest Extended Function Number + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000001 -- EAX: AMD Family, Model, Stepping +# EBX: BrandId Identifier +# ECX: Feature Identifiers +# EDX: Feature Identifiers + limm rax, 0x00020f51, dataSize=4 + limm rbx, 0x00000405, dataSize=4 + limm rdx, 0xe3d3fbff, dataSize=4 + limm rcx, 0x00000001, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000002 -- Processor Name String Identifier + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000003 -- Processor Name String Identifier + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000004 -- Processor Name String Identifier + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000005 -- L1 Cache and TLB Identifiers + limm rax, 0xff08ff08, dataSize=4 + limm rbx, 0xff20ff20, dataSize=4 + limm rdx, 0x40020140, dataSize=4 + limm rcx, 0x40020140, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000006 -- L2/L3 Cache and L2 TLB Identifiers + limm rax, 0x00000000, dataSize=4 + limm rbx, 0x42004200, dataSize=4 + limm rdx, 0x00000000, dataSize=4 + limm rcx, 0x04008140, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000007 -- Advanced Power Management Information + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000008 -- Long Mode Address Size Identification + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000009 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x8000000A -- SVM Revision and Feature Identification + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x8000000B -- Reserved + # JUNK VALUES limm rax, 0x80000018, dataSize=4 limm rbx, 0x68747541, dataSize=4 limm rdx, 0x69746e65, dataSize=4 limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x8000000C -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x8000000D -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x8000000E -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x8000000F -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000010 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000011 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000012 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000013 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000014 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000015 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000016 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000017 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +# 0x80000018 -- Reserved + # JUNK VALUES + limm rax, 0x80000018, dataSize=4 + limm rbx, 0x68747541, dataSize=4 + limm rdx, 0x69746e65, dataSize=4 + limm rcx, 0x444d4163, dataSize=4 + bri t0, label("end") + fault "NoFault" + fault "NoFault" + fault "NoFault" + +end: + fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/rotate_and_shift/shift.py b/src/arch/x86/isa/insts/rotate_and_shift/shift.py index 45758b489..6c688cca3 100644 --- a/src/arch/x86/isa/insts/rotate_and_shift/shift.py +++ b/src/arch/x86/isa/insts/rotate_and_shift/shift.py @@ -56,13 +56,13 @@ microcode = ''' def macroop SAL_R_I { - slli reg, reg, imm + slli reg, reg, imm, flags=(SF,ZF,PF) }; def macroop SAL_M_I { ld t1, seg, sib, disp - slli t1, t1, imm + slli t1, t1, imm, flags=(SF,ZF,PF) st t1, seg, sib, disp }; @@ -70,19 +70,19 @@ def macroop SAL_P_I { rdip t7 ld t1, seg, riprel, disp - slli t1, t1, imm + slli t1, t1, imm, flags=(SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAL_1_R { - slli reg, reg, 1 + slli reg, reg, 1, flags=(SF,ZF,PF) }; def macroop SAL_1_M { ld t1, seg, sib, disp - slli t1, t1, 1 + slli t1, t1, 1, flags=(SF,ZF,PF) st t1, seg, sib, disp }; @@ -90,19 +90,19 @@ def macroop SAL_1_P { rdip t7 ld t1, seg, riprel, disp - slli t1, t1, 1 + slli t1, t1, 1, flags=(SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAL_R_R { - sll reg, reg, regm + sll reg, reg, regm, flags=(SF,ZF,PF) }; def macroop SAL_M_R { ld t1, seg, sib, disp - sll t1, t1, reg + sll t1, t1, reg, flags=(SF,ZF,PF) st t1, seg, sib, disp }; @@ -110,19 +110,19 @@ def macroop SAL_P_R { rdip t7 ld t1, seg, riprel, disp - sll t1, t1, reg + sll t1, t1, reg, flags=(SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SHR_R_I { - srli reg, reg, imm + srli reg, reg, imm, flags=(SF,ZF,PF) }; def macroop SHR_M_I { ld t1, seg, sib, disp - srli t1, t1, imm + srli t1, t1, imm, flags=(SF,ZF,PF) st t1, seg, sib, disp }; @@ -130,19 +130,19 @@ def macroop SHR_P_I { rdip t7 ld t1, seg, riprel, disp - srli t1, t1, imm + srli t1, t1, imm, flags=(SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SHR_1_R { - srli reg, reg, 1 + srli reg, reg, 1, flags=(SF,ZF,PF) }; def macroop SHR_1_M { ld t1, seg, sib, disp - srli t1, t1, 1 + srli t1, t1, 1, flags=(SF,ZF,PF) st t1, seg, sib, disp }; @@ -150,19 +150,19 @@ def macroop SHR_1_P { rdip t7 ld t1, seg, riprel, disp - srli t1, t1, 1 + srli t1, t1, 1, flags=(SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SHR_R_R { - srl reg, reg, regm + srl reg, reg, regm, flags=(SF,ZF,PF) }; def macroop SHR_M_R { ld t1, seg, sib, disp - srl t1, t1, reg + srl t1, t1, reg, flags=(SF,ZF,PF) st t1, seg, sib, disp }; @@ -170,19 +170,19 @@ def macroop SHR_P_R { rdip t7 ld t1, seg, riprel, disp - srl t1, t1, reg + srl t1, t1, reg, flags=(SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAR_R_I { - srai reg, reg, imm + srai reg, reg, imm, flags=(SF,ZF,PF) }; def macroop SAR_M_I { ld t1, seg, sib, disp - srai t1, t1, imm + srai t1, t1, imm, flags=(SF,ZF,PF) st t1, seg, sib, disp }; @@ -190,19 +190,19 @@ def macroop SAR_P_I { rdip t7 ld t1, seg, riprel, disp - srai t1, t1, imm + srai t1, t1, imm, flags=(SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAR_1_R { - srai reg, reg, 1 + srai reg, reg, 1, flags=(SF,ZF,PF) }; def macroop SAR_1_M { ld t1, seg, sib, disp - srai t1, t1, 1 + srai t1, t1, 1, flags=(SF,ZF,PF) st t1, seg, sib, disp }; @@ -210,19 +210,19 @@ def macroop SAR_1_P { rdip t7 ld t1, seg, riprel, disp - srai t1, t1, 1 + srai t1, t1, 1, flags=(SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAR_R_R { - sra reg, reg, regm + sra reg, reg, regm, flags=(SF,ZF,PF) }; def macroop SAR_M_R { ld t1, seg, sib, disp - sra t1, t1, reg + sra t1, t1, reg, flags=(SF,ZF,PF) st t1, seg, sib, disp }; @@ -230,7 +230,7 @@ def macroop SAR_P_R { rdip t7 ld t1, seg, riprel, disp - sra t1, t1, reg + sra t1, t1, reg, flags=(SF,ZF,PF) st t1, seg, riprel, disp }; ''' diff --git a/src/arch/x86/isa/insts/string/compare_strings.py b/src/arch/x86/isa/insts/string/compare_strings.py index 1484c4706..71b8511b4 100644 --- a/src/arch/x86/isa/insts/string/compare_strings.py +++ b/src/arch/x86/isa/insts/string/compare_strings.py @@ -53,16 +53,60 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class CMPS(Inst): -# "GenFault ${new UnimpInstFault}" -# class CMPSB(Inst): -# "GenFault ${new UnimpInstFault}" -# class CMPSW(Inst): -# "GenFault ${new UnimpInstFault}" -# class CMPSD(Inst): -# "GenFault ${new UnimpInstFault}" -# class CMPSQ(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop CMPS_M_M { + # Find the constant we need to either add or subtract from rdi + ruflag t0, 10 + movi t3, t3, dsz, flags=(CEZF,), dataSize=asz + subi t4, t0, dsz, dataSize=asz + mov t3, t3, t4, flags=(nCEZF,), dataSize=asz + + ld t1, seg, [1, t0, rsi] + ld t2, es, [1, t0, rdi] + sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) + + add rdi, rdi, t3, dataSize=asz + add rsi, rsi, t3, dataSize=asz +}; + +# +# Versions which have the rep prefix. These could benefit from some loop +# unrolling. +# + +def macroop CMPS_E_M_M { + # Find the constant we need to either add or subtract from rdi + ruflag t0, 10 + movi t3, t3, dsz, flags=(CEZF,), dataSize=asz + subi t4, t0, dsz, dataSize=asz + mov t3, t3, t4, flags=(nCEZF,), dataSize=asz + + ld t1, seg, [1, t0, rsi] + ld t2, es, [1, t0, rdi] + sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) + + subi rcx, rcx, 1, flags=(EZF,), dataSize=asz + add rdi, rdi, t3, dataSize=asz + add rsi, rsi, t3, dataSize=asz + bri t0, 4, flags=(CSTRZnEZF,) + fault "NoFault" +}; + +def macroop CMPS_N_M_M { + # Find the constant we need to either add or subtract from rdi + ruflag t0, 10 + movi t3, t3, dsz, flags=(CEZF,), dataSize=asz + subi t4, t0, dsz, dataSize=asz + mov t3, t3, t4, flags=(nCEZF,), dataSize=asz + + ld t1, seg, [1, t0, rsi] + ld t2, es, [1, t0, rdi] + sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) + + subi rcx, rcx, 1, flags=(EZF,), dataSize=asz + add rdi, rdi, t3, dataSize=asz + add rsi, rsi, t3, dataSize=asz + bri t0, 4, flags=(CSTRnZnEZF,) + fault "NoFault" +}; +''' diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index 4675b9d56..fdfea6136 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -126,6 +126,8 @@ def template MacroDeclare {{ */ class %(class_name)s : public %(base_class)s { + private: + %(declareLabels)s public: // Constructor. %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env); @@ -151,6 +153,9 @@ def template MacroConstructor {{ let {{ from micro_asm import Combinational_Macroop, Rom_Macroop class X86Macroop(Combinational_Macroop): + def add_microop(self, microop): + microop.micropc = len(self.microops) + self.microops.append(microop) def setAdjustEnv(self, val): self.adjust_env = val def __init__(self, name): @@ -166,7 +171,14 @@ let {{ def getDeclaration(self): #FIXME This first parameter should be the mnemonic. I need to #write some code which pulls that out - iop = InstObjParams(self.name, self.name, "Macroop", {"code" : ""}) + declareLabels = "" + for (label, microop) in self.labels.items(): + declareLabels += "const static uint64_t label_%s = %d;\n" \ + % (label, microop.micropc) + iop = InstObjParams(self.name, self.name, "Macroop", + {"code" : "", + "declareLabels" : declareLabels + }) return MacroDeclare.subst(iop); def getDefinition(self): #FIXME This first parameter should be the mnemonic. I need to diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index af3148631..929fd0075 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -125,5 +125,10 @@ let {{ env.dataSize = 8; ''' + def labeler(labelStr): + return "label_%s" % labelStr + + assembler.symbols["label"] = labeler + macroopDict = assembler.assemble(microcode) }}; diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 403a1aacf..c979ace04 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -123,19 +123,7 @@ def template MicroLoadExecute {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - Twin64_t alignedMem; - fault = read(xc, EA, alignedMem, 0); - int offset = EA & (dataSize - 1); - if(dataSize != 8 || !offset) - { - Mem = bits(alignedMem.a, - (offset + dataSize) * 8 - 1, offset * 8); - } - else - { - Mem = alignedMem.b << (dataSize - offset) * 8; - Mem |= bits(alignedMem.a, dataSize * 8 - 1, offset * 8); - } + fault = read(xc, EA, Mem, 0); if(fault == NoFault) { @@ -162,9 +150,7 @@ def template MicroLoadInitiateAcc {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - int offset = EA & (dataSize - 1); - Twin64_t alignedMem; - fault = read(xc, EA, alignedMem, offset); + fault = read(xc, EA, Mem, 0); return fault; } @@ -180,18 +166,8 @@ def template MicroLoadCompleteAcc {{ %(op_decl)s; %(op_rd)s; - Twin64_t alignedMem = pkt->get<Twin64_t>(); - int offset = pkt->req->getFlags(); - if(dataSize != 8 || !offset) - { - Mem = bits(alignedMem.a, - (offset + dataSize) * 8 - 1, offset * 8); - } - else - { - Mem = alignedMem.b << (dataSize - offset) * 8; - Mem |= bits(alignedMem.a, dataSize * 8 - 1, offset * 8); - } + Mem = pkt->get<typeof(Mem)>(); + %(code)s; if(fault == NoFault) @@ -221,14 +197,7 @@ def template MicroStoreExecute {{ if(fault == NoFault) { - int offset = EA & (dataSize - 1); - - Twin64_t alignedMem; - alignedMem.a = Mem << (offset * 8); - alignedMem.b = - bits(Mem, dataSize * 8 - 1, (dataSize - offset) * 8); - - fault = write(xc, alignedMem, EA, 0); + fault = write(xc, Mem, EA, 0); if(fault == NoFault) { %(op_wb)s; @@ -255,14 +224,7 @@ def template MicroStoreInitiateAcc {{ if(fault == NoFault) { - int offset = EA & (dataSize - 1); - - Twin64_t alignedMem; - alignedMem.a = Mem << (offset * 8); - alignedMem.b = - bits(Mem, dataSize * 8 - 1, (dataSize - offset) * 8); - - fault = write(xc, alignedMem, EA, 0); + fault = write(xc, Mem, EA, 0); if(fault == NoFault) { %(op_wb)s; diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 608b86a70..616f7a5fc 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -652,17 +652,19 @@ let {{ defineMicroRegOpRd('Rdip', 'DestReg = RIP') defineMicroRegOpRd('Ruflags', 'DestReg = ccFlagBits') defineMicroRegOpRdImm('Ruflag', ''' - int flag = bits(ccFlagBits, (1 << imm8) + 0*psrc1); + int flag = bits(ccFlagBits, imm8 + 0*psrc1); DestReg = merge(DestReg, flag, dataSize); - ccFlagBits = ccFlagBits & ~EZFBit; - ccFlagBits = ccFlagBits | ((flag == 0) ? EZFBit : 0); + ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : + (ccFlagBits & ~EZFBit); ''') defineMicroRegOpImm('Sext', ''' IntReg val = psrc1; int sign_bit = bits(val, imm8-1, imm8-1); - val = sign_bit ? (val | ~mask(imm8)) : val; - DestReg = merge(DestReg, val, dataSize);''') + uint64_t maskVal = mask(imm8); + val = sign_bit ? (val | ~maskVal) : (val & maskVal); + DestReg = merge(DestReg, val, dataSize); + ''') defineMicroRegOpImm('Zext', 'DestReg = bits(psrc1, imm8-1, 0);') }}; diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 364050994..79422998d 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -93,6 +93,7 @@ #include "base/loader/object_file.hh" #include "base/loader/elf_object.hh" #include "base/misc.hh" +#include "base/trace.hh" #include "cpu/thread_context.hh" #include "mem/page_table.hh" #include "mem/translating_port.hh" diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc new file mode 100644 index 000000000..e29ec58c2 --- /dev/null +++ b/src/arch/x86/tlb.cc @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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. + * + * Authors: Gabe Black + */ + +#include <cstring> + +#include "arch/x86/tlb.hh" +#include "params/X86DTB.hh" +#include "params/X86ITB.hh" +#include "sim/serialize.hh" + +namespace X86ISA { + void + TlbEntry::serialize(std::ostream &os) + { + SERIALIZE_SCALAR(pageStart); + } + + void + TlbEntry::unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(pageStart); + } +}; + +X86ISA::ITB * +X86ITBParams::create() +{ + return new X86ISA::ITB(name); +} + +X86ISA::DTB * +X86DTBParams::create() +{ + return new X86ISA::DTB(name); +} diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh index c19ce0b29..4cf65ac08 100644 --- a/src/arch/x86/tlb.hh +++ b/src/arch/x86/tlb.hh @@ -58,10 +58,39 @@ #ifndef __ARCH_X86_TLB_HH__ #define __ARCH_X86_TLB_HH__ -#error X86 is not yet supported! +#include <iostream> +#include <string> + +#include "sim/host.hh" +#include "sim/tlb.hh" + +class Checkpoint; namespace X86ISA { + struct TlbEntry + { + Addr pageStart; + TlbEntry() {} + TlbEntry(Addr paddr) : pageStart(paddr) {} + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + }; + + class ITB : public GenericITB<false, false> + { + public: + ITB(const std::string &name) : GenericITB<false, false>(name) + {} + }; + + class DTB : public GenericDTB<false, false> + { + public: + DTB(const std::string &name) : GenericDTB<false, false>(name) + {} + }; }; #endif // __ARCH_X86_TLB_HH__ diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 7a51650e6..9b2b99c58 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -37,12 +37,14 @@ import sys default_tracer = ExeTracer() -if build_env['FULL_SYSTEM']: - if build_env['TARGET_ISA'] == 'alpha': - from AlphaTLB import AlphaDTB, AlphaITB - - if build_env['TARGET_ISA'] == 'sparc': - from SparcTLB import SparcDTB, SparcITB +if build_env['TARGET_ISA'] == 'alpha': + from AlphaTLB import AlphaDTB, AlphaITB +elif build_env['TARGET_ISA'] == 'sparc': + from SparcTLB import SparcDTB, SparcITB +elif build_env['TARGET_ISA'] == 'x86': + from X86TLB import X86DTB, X86ITB +elif build_env['TARGET_ISA'] == 'mips': + from MipsTLB import MipsDTB, MipsITB class BaseCPU(SimObject): type = 'BaseCPU' @@ -57,19 +59,26 @@ class BaseCPU(SimObject): "enable checkpoint pseudo instructions") do_statistics_insts = Param.Bool(True, "enable statistics pseudo instructions") - - if build_env['TARGET_ISA'] == 'sparc': - dtb = Param.SparcDTB(SparcDTB(), "Data TLB") - itb = Param.SparcITB(SparcITB(), "Instruction TLB") - elif build_env['TARGET_ISA'] == 'alpha': - dtb = Param.AlphaDTB(AlphaDTB(), "Data TLB") - itb = Param.AlphaITB(AlphaITB(), "Instruction TLB") - else: - print "Unknown architecture, can't pick TLBs" - sys.exit(1) else: workload = VectorParam.Process("processes to run") + if build_env['TARGET_ISA'] == 'sparc': + dtb = Param.SparcDTB(SparcDTB(), "Data TLB") + itb = Param.SparcITB(SparcITB(), "Instruction TLB") + elif build_env['TARGET_ISA'] == 'alpha': + dtb = Param.AlphaDTB(AlphaDTB(), "Data TLB") + itb = Param.AlphaITB(AlphaITB(), "Instruction TLB") + elif build_env['TARGET_ISA'] == 'x86': + dtb = Param.X86DTB(X86DTB(), "Data TLB") + itb = Param.X86ITB(X86ITB(), "Instruction TLB") + elif build_env['TARGET_ISA'] == 'mips': + dtb = Param.MipsDTB(MipsDTB(), "Data TLB") + itb = Param.MipsITB(MipsITB(), "Instruction TLB") + else: + print "Don't know what TLB to use for ISA %s" % \ + build_env['TARGET_ISA'] + sys.exit(1) + max_insts_all_threads = Param.Counter(0, "terminate when all threads have reached this inst count") max_insts_any_thread = Param.Counter(0, diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 362babeff..0f2a90bf6 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -847,12 +847,6 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags) req->setVirt(asid, addr, sizeof(T), flags, this->PC); req->setThreadContext(thread->readCpuId(), threadNumber); - if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() > - TheISA::VMPageSize) { - delete req; - return TheISA::genAlignmentFault(); - } - fault = cpu->translateDataReadReq(req, thread); if (req->isUncacheable()) @@ -909,12 +903,6 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res) req->setVirt(asid, addr, sizeof(T), flags, this->PC); req->setThreadContext(thread->readCpuId(), threadNumber); - if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() > - TheISA::VMPageSize) { - delete req; - return TheISA::genAlignmentFault(); - } - fault = cpu->translateDataWriteReq(req, thread); if (req->isUncacheable()) diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 3b4d21e13..15454c3fe 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -84,15 +84,15 @@ class CheckerThreadContext : public ThreadContext int readCpuId() { return actualTC->readCpuId(); } + TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); } + + TheISA::DTB *getDTBPtr() { return actualTC->getDTBPtr(); } + #if FULL_SYSTEM System *getSystemPtr() { return actualTC->getSystemPtr(); } PhysicalMemory *getPhysMemPtr() { return actualTC->getPhysMemPtr(); } - TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); } - - TheISA::DTB *getDTBPtr() { return actualTC->getDTBPtr(); } - TheISA::Kernel::Statistics *getKernelStats() { return actualTC->getKernelStats(); } diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py index e691cfe5d..27ca8ce1e 100644 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@ -52,8 +52,8 @@ class DerivO3CPU(BaseCPU): else: checker = Param.BaseCPU(O3Checker(exitOnError=False, updateOnError=True, warnOnlyOnLoadError=False), "checker") - checker.itb = Parent.itb - checker.dtb = Parent.dtb + checker.itb = Parent.itb + checker.dtb = Parent.dtb cachePorts = Param.Unsigned(200, "Cache Ports") icache_port = Port("Instruction Port") diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index 676893098..ebc4e7b23 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -66,45 +66,6 @@ class AlphaO3CPU : public FullO3CPU<Impl> /** Registers statistics. */ void regStats(); -#if FULL_SYSTEM - /** Translates instruction requestion. */ - Fault translateInstReq(RequestPtr &req, Thread *thread) - { - return this->itb->translate(req, thread->getTC()); - } - - /** Translates data read request. */ - Fault translateDataReadReq(RequestPtr &req, Thread *thread) - { - return this->dtb->translate(req, thread->getTC(), false); - } - - /** Translates data write request. */ - Fault translateDataWriteReq(RequestPtr &req, Thread *thread) - { - return this->dtb->translate(req, thread->getTC(), true); - } - -#else - /** Translates instruction requestion in syscall emulation mode. */ - Fault translateInstReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data read request in syscall emulation mode. */ - Fault translateDataReadReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data write request in syscall emulation mode. */ - Fault translateDataWriteReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - -#endif /** Reads a miscellaneous register. */ TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); diff --git a/src/cpu/o3/alpha/cpu_builder.cc b/src/cpu/o3/alpha/cpu_builder.cc index 4db217abf..1aa3d1618 100644 --- a/src/cpu/o3/alpha/cpu_builder.cc +++ b/src/cpu/o3/alpha/cpu_builder.cc @@ -77,10 +77,11 @@ DerivO3CPUParams::create() params->cpu_id = cpu_id; params->activity = activity; -#if FULL_SYSTEM - params->system = system; params->itb = itb; params->dtb = dtb; + +#if FULL_SYSTEM + params->system = system; params->profile = profile; params->do_quiesce = do_quiesce; diff --git a/src/cpu/o3/alpha/params.hh b/src/cpu/o3/alpha/params.hh index b6b84b2a1..164c25312 100644 --- a/src/cpu/o3/alpha/params.hh +++ b/src/cpu/o3/alpha/params.hh @@ -54,10 +54,8 @@ class AlphaSimpleParams : public O3Params { public: -#if FULL_SYSTEM AlphaISA::ITB *itb; AlphaISA::DTB *dtb; -#endif }; #endif // __CPU_O3_ALPHA_PARAMS_HH__ diff --git a/src/cpu/o3/checker_builder.cc b/src/cpu/o3/checker_builder.cc index 97425b08c..0799b9cb5 100644 --- a/src/cpu/o3/checker_builder.cc +++ b/src/cpu/o3/checker_builder.cc @@ -86,9 +86,9 @@ O3CheckerParams::create() params->progress_interval = 0; temp2++; -#if FULL_SYSTEM params->itb = itb; params->dtb = dtb; +#if FULL_SYSTEM params->system = system; params->cpu_id = cpu_id; params->profile = profile; diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index cae6ae20c..98e200944 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -150,10 +150,8 @@ FullO3CPU<Impl>::DeallocateContextEvent::description() template <class Impl> FullO3CPU<Impl>::FullO3CPU(O3CPU *o3_cpu, Params *params) : BaseO3CPU(params), -#if FULL_SYSTEM itb(params->itb), dtb(params->dtb), -#endif tickEvent(this), removeInstsThisCycle(false), fetch(o3_cpu, params), diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 84a7c8673..d97a2080d 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -94,9 +94,9 @@ class FullO3CPU : public BaseO3CPU public: // Typedefs from the Impl here. typedef typename Impl::CPUPol CPUPolicy; - typedef typename Impl::Params Params; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::O3CPU O3CPU; + typedef typename Impl::Params Params; typedef O3ThreadState<Impl> Thread; @@ -113,10 +113,8 @@ class FullO3CPU : public BaseO3CPU SwitchedOut }; -#if FULL_SYSTEM TheISA::ITB * itb; TheISA::DTB * dtb; -#endif /** Overall CPU status. */ Status _status; @@ -265,6 +263,24 @@ class FullO3CPU : public BaseO3CPU /** Registers statistics. */ void fullCPURegStats(); + /** Translates instruction requestion. */ + Fault translateInstReq(RequestPtr &req, Thread *thread) + { + return this->itb->translate(req, thread->getTC()); + } + + /** Translates data read request. */ + Fault translateDataReadReq(RequestPtr &req, Thread *thread) + { + return this->dtb->translate(req, thread->getTC(), false); + } + + /** Translates data write request. */ + Fault translateDataWriteReq(RequestPtr &req, Thread *thread) + { + return this->dtb->translate(req, thread->getTC(), true); + } + /** Returns a specific port. */ Port *getPort(const std::string &if_name, int idx); diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 5a5d19b64..7d344fa33 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -1228,7 +1228,6 @@ DefaultFetch<Impl>::fetch(bool &status_change) // Send the fault to commit. This thread will not do anything // until commit handles the fault. The only other way it can // wake up is if a squash comes along and changes the PC. -#if FULL_SYSTEM assert(numInst < fetchWidth); // Get a sequence number. inst_seq = cpu->getAndIncrementInstSeq(); @@ -1240,7 +1239,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) fetch_PC, fetch_NPC, fetch_MicroPC, next_PC, next_NPC, next_MicroPC, inst_seq, cpu); - instruction->setPredTarg(next_PC, next_NPC, 1); + instruction->setPredTarg(next_NPC, next_NPC + instSize, 0); instruction->setTid(tid); instruction->setASID(tid); @@ -1260,11 +1259,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) fetchStatus[tid] = TrapPending; status_change = true; -#else // !FULL_SYSTEM - fetchStatus[tid] = TrapPending; - status_change = true; -#endif // FULL_SYSTEM DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %08p", tid, fault->name(), PC[tid]); } diff --git a/src/cpu/o3/mips/cpu.hh b/src/cpu/o3/mips/cpu.hh index 0361c1814..3724ced46 100755 --- a/src/cpu/o3/mips/cpu.hh +++ b/src/cpu/o3/mips/cpu.hh @@ -68,24 +68,6 @@ class MipsO3CPU : public FullO3CPU<Impl> /** Registers statistics. */ void regStats(); - /** Translates instruction requestion in syscall emulation mode. */ - Fault translateInstReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data read request in syscall emulation mode. */ - Fault translateDataReadReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data write request in syscall emulation mode. */ - Fault translateDataWriteReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - /** Reads a miscellaneous register. */ TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); diff --git a/src/cpu/o3/mips/params.hh b/src/cpu/o3/mips/params.hh index d1ac62e21..2688d3fb3 100644 --- a/src/cpu/o3/mips/params.hh +++ b/src/cpu/o3/mips/params.hh @@ -36,8 +36,11 @@ #include "cpu/o3/params.hh" //Forward declarations -//class MipsDTB; -//class MipsITB; +namespace MipsISA +{ + class MipsDTB; + class MipsITB; +} class MemObject; class Process; class System; @@ -53,11 +56,9 @@ class MipsSimpleParams : public O3Params public: MipsSimpleParams() {} -#if FULL_SYSTEM //Full System Paramater Objects place here - MipsITB *itb; - MipsDTB *dtb; -#endif + MipsISA::ITB *itb; + MipsISA::DTB *dtb; }; #endif // __CPU_O3_MIPS_PARAMS_HH__ diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh index 7b932e429..3fd193e0f 100644 --- a/src/cpu/o3/sparc/cpu.hh +++ b/src/cpu/o3/sparc/cpu.hh @@ -66,45 +66,6 @@ class SparcO3CPU : public FullO3CPU<Impl> /** Registers statistics. */ void regStats(); -#if FULL_SYSTEM - /** Translates instruction requestion. */ - Fault translateInstReq(RequestPtr &req, Thread *thread) - { - return this->itb->translate(req, thread->getTC()); - } - - /** Translates data read request. */ - Fault translateDataReadReq(RequestPtr &req, Thread *thread) - { - return this->dtb->translate(req, thread->getTC(), false); - } - - /** Translates data write request. */ - Fault translateDataWriteReq(RequestPtr &req, Thread *thread) - { - return this->dtb->translate(req, thread->getTC(), true); - } - -#else - /** Translates instruction requestion in syscall emulation mode. */ - Fault translateInstReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data read request in syscall emulation mode. */ - Fault translateDataReadReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data write request in syscall emulation mode. */ - Fault translateDataWriteReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - -#endif /** Reads a miscellaneous register. */ TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); diff --git a/src/cpu/o3/sparc/cpu_builder.cc b/src/cpu/o3/sparc/cpu_builder.cc index 49f0f455d..b7c684431 100644 --- a/src/cpu/o3/sparc/cpu_builder.cc +++ b/src/cpu/o3/sparc/cpu_builder.cc @@ -78,10 +78,11 @@ DerivO3CPUParams::create() params->cpu_id = cpu_id; params->activity = activity; -#if FULL_SYSTEM - params->system = system; params->itb = itb; params->dtb = dtb; + +#if FULL_SYSTEM + params->system = system; params->profile = profile; params->do_quiesce = do_quiesce; diff --git a/src/cpu/o3/sparc/params.hh b/src/cpu/o3/sparc/params.hh index d399d64c4..09f523818 100644 --- a/src/cpu/o3/sparc/params.hh +++ b/src/cpu/o3/sparc/params.hh @@ -54,10 +54,8 @@ class SparcSimpleParams : public O3Params { public: -#if FULL_SYSTEM SparcISA::ITB *itb; SparcISA::DTB *dtb; -#endif }; #endif // __CPU_O3_SPARC_PARAMS_HH__ diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 93638673b..31e08db4c 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -66,13 +66,11 @@ class O3ThreadContext : public ThreadContext /** Pointer to the thread state that this TC corrseponds to. */ O3ThreadState<Impl> *thread; -#if FULL_SYSTEM /** Returns a pointer to the ITB. */ TheISA::ITB *getITBPtr() { return cpu->itb; } /** Returns a pointer to the DTB. */ TheISA::DTB *getDTBPtr() { return cpu->dtb; } -#endif /** Returns a pointer to this CPU. */ virtual BaseCPU *getCpuPtr() { return cpu; } diff --git a/src/cpu/ozone/checker_builder.cc b/src/cpu/ozone/checker_builder.cc index f813e5df2..625b2a39a 100644 --- a/src/cpu/ozone/checker_builder.cc +++ b/src/cpu/ozone/checker_builder.cc @@ -87,9 +87,9 @@ OzoneCheckerParams::create() temp2++; params->progress_interval = 0; -#if FULL_SYSTEM params->itb = itb; params->dtb = dtb; +#if FULL_SYSTEM params->system = system; params->cpu_id = cpu_id; params->profile = profile; diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 92b00af26..78d0892c4 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -120,15 +120,15 @@ class OzoneCPU : public BaseCPU int readCpuId() { return thread->readCpuId(); } + TheISA::ITB *getITBPtr() { return cpu->itb; } + + TheISA::DTB * getDTBPtr() { return cpu->dtb; } + #if FULL_SYSTEM System *getSystemPtr() { return cpu->system; } PhysicalMemory *getPhysMemPtr() { return cpu->physmem; } - TheISA::ITB *getITBPtr() { return cpu->itb; } - - TheISA::DTB * getDTBPtr() { return cpu->dtb; } - TheISA::Kernel::Statistics *getKernelStats() { return thread->getKernelStats(); } diff --git a/src/cpu/ozone/cpu_builder.cc b/src/cpu/ozone/cpu_builder.cc index 60ee9c4f9..7edbe41c9 100644 --- a/src/cpu/ozone/cpu_builder.cc +++ b/src/cpu/ozone/cpu_builder.cc @@ -79,11 +79,12 @@ DerivOzoneCPUParams::create() params->name = name; params->numberOfThreads = actual_num_threads; + params->itb = itb; + params->dtb = dtb; + #if FULL_SYSTEM params->system = system; params->cpu_id = cpu_id; - params->itb = itb; - params->dtb = dtb; params->profile = profile; params->do_quiesce = do_quiesce; params->do_checkpoint_insts = do_checkpoint_insts; diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index d73e5768a..37a91c630 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -129,6 +129,8 @@ OzoneCPU<Impl>::OzoneCPU(Params *p) thread.inSyscall = false; thread.setStatus(ThreadContext::Suspended); + itb = p->itb; + dtb = p->dtb; #if FULL_SYSTEM // Setup thread state stuff. thread.cpu = this; @@ -137,8 +139,6 @@ OzoneCPU<Impl>::OzoneCPU(Params *p) thread.quiesceEvent = new EndQuiesceEvent(tc); system = p->system; - itb = p->itb; - dtb = p->dtb; physmem = p->system->physmem; if (p->profile) { diff --git a/src/cpu/ozone/simple_cpu_builder.cc b/src/cpu/ozone/simple_cpu_builder.cc index df8e25fd0..ca55cdca4 100644 --- a/src/cpu/ozone/simple_cpu_builder.cc +++ b/src/cpu/ozone/simple_cpu_builder.cc @@ -82,11 +82,12 @@ SimpleOzoneCPUParams::create() params->name = name; params->numberOfThreads = actual_num_threads; + params->itb = itb; + params->dtb = dtb; + #if FULL_SYSTEM params->system = system; params->cpu_id = cpu_id; - params->itb = itb; - params->dtb = dtb; #else params->workload = workload; // params->pTable = page_table; diff --git a/src/cpu/ozone/simple_params.hh b/src/cpu/ozone/simple_params.hh index d5ba6a923..ec5782c8a 100644 --- a/src/cpu/ozone/simple_params.hh +++ b/src/cpu/ozone/simple_params.hh @@ -55,9 +55,8 @@ class SimpleParams : public BaseCPU::Params { public: -#if FULL_SYSTEM TheISA::ITB *itb; TheISA::DTB *dtb; -#else +#if !FULL_SYSTEM std::vector<Process *> workload; #endif // FULL_SYSTEM diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 80faad6e2..06f52e30e 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -285,47 +285,82 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) { // use the CPU's statically allocated read request and packet objects Request *req = &data_read_req; - req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); if (traceData) { traceData->setAddr(addr); } - // translate to physical address - Fault fault = thread->translateDataReadReq(req); - - // Now do the access. - if (fault == NoFault) { - Packet pkt = - Packet(req, - req->isLocked() ? MemCmd::LoadLockedReq : MemCmd::ReadReq, - Packet::Broadcast); - pkt.dataStatic(&data); - - if (req->isMmapedIpr()) - dcache_latency = TheISA::handleIprRead(thread->getTC(), &pkt); - else { - if (hasPhysMemPort && pkt.getAddr() == physMemAddr) - dcache_latency = physmemPort.sendAtomic(&pkt); - else - dcache_latency = dcachePort.sendAtomic(&pkt); - } - dcache_access = true; + //The block size of our peer. + int blockSize = dcachePort.peerBlockSize(); + //The size of the data we're trying to read. + int dataSize = sizeof(T); + + uint8_t * dataPtr = (uint8_t *)&data; + + //The address of the second part of this access if it needs to be split + //across a cache line boundary. + Addr secondAddr = roundDown(addr + dataSize - 1, blockSize); + + if(secondAddr > addr) + dataSize = secondAddr - addr; + + dcache_latency = 0; - assert(!pkt.isError()); + while(1) { + req->setVirt(0, addr, dataSize, flags, thread->readPC()); - data = gtoh(data); + // translate to physical address + Fault fault = thread->translateDataReadReq(req); - if (req->isLocked()) { - TheISA::handleLockedRead(thread, req); + // Now do the access. + if (fault == NoFault) { + Packet pkt = Packet(req, + req->isLocked() ? MemCmd::LoadLockedReq : MemCmd::ReadReq, + Packet::Broadcast); + pkt.dataStatic(dataPtr); + + if (req->isMmapedIpr()) + dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt); + else { + if (hasPhysMemPort && pkt.getAddr() == physMemAddr) + dcache_latency += physmemPort.sendAtomic(&pkt); + else + dcache_latency += dcachePort.sendAtomic(&pkt); + } + dcache_access = true; + + assert(!pkt.isError()); + + if (req->isLocked()) { + TheISA::handleLockedRead(thread, req); + } } - } - // This will need a new way to tell if it has a dcache attached. - if (req->isUncacheable()) - recordEvent("Uncached Read"); + // This will need a new way to tell if it has a dcache attached. + if (req->isUncacheable()) + recordEvent("Uncached Read"); + + //If there's a fault, return it + if (fault != NoFault) + return fault; + //If we don't need to access a second cache line, stop now. + if (secondAddr <= addr) + { + data = gtoh(data); + return fault; + } + + /* + * Set up for accessing the second cache line. + */ - return fault; + //Move the pointer we're reading into to the correct location. + dataPtr += dataSize; + //Adjust the size to get the remaining bytes. + dataSize = addr + sizeof(T) - secondAddr; + //And access the right address. + addr = secondAddr; + } } #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -385,65 +420,105 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { // use the CPU's statically allocated write request and packet objects Request *req = &data_write_req; - req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); if (traceData) { traceData->setAddr(addr); } - // translate to physical address - Fault fault = thread->translateDataWriteReq(req); - - // Now do the access. - if (fault == NoFault) { - MemCmd cmd = MemCmd::WriteReq; // default - bool do_access = true; // flag to suppress cache access - - if (req->isLocked()) { - cmd = MemCmd::StoreCondReq; - do_access = TheISA::handleLockedWrite(thread, req); - } else if (req->isSwap()) { - cmd = MemCmd::SwapReq; - if (req->isCondSwap()) { - assert(res); - req->setExtraData(*res); - } - } + //The block size of our peer. + int blockSize = dcachePort.peerBlockSize(); + //The size of the data we're trying to read. + int dataSize = sizeof(T); - if (do_access) { - Packet pkt = Packet(req, cmd, Packet::Broadcast); - pkt.dataStatic(&data); + uint8_t * dataPtr = (uint8_t *)&data; - if (req->isMmapedIpr()) { - dcache_latency = TheISA::handleIprWrite(thread->getTC(), &pkt); - } else { - data = htog(data); - if (hasPhysMemPort && pkt.getAddr() == physMemAddr) - dcache_latency = physmemPort.sendAtomic(&pkt); - else - dcache_latency = dcachePort.sendAtomic(&pkt); + //The address of the second part of this access if it needs to be split + //across a cache line boundary. + Addr secondAddr = roundDown(addr + dataSize - 1, blockSize); + + if(secondAddr > addr) + dataSize = secondAddr - addr; + + dcache_latency = 0; + + while(1) { + req->setVirt(0, addr, dataSize, flags, thread->readPC()); + + // translate to physical address + Fault fault = thread->translateDataWriteReq(req); + + // Now do the access. + if (fault == NoFault) { + MemCmd cmd = MemCmd::WriteReq; // default + bool do_access = true; // flag to suppress cache access + + if (req->isLocked()) { + cmd = MemCmd::StoreCondReq; + do_access = TheISA::handleLockedWrite(thread, req); + } else if (req->isSwap()) { + cmd = MemCmd::SwapReq; + if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } + } + + if (do_access) { + Packet pkt = Packet(req, cmd, Packet::Broadcast); + pkt.dataStatic(dataPtr); + + if (req->isMmapedIpr()) { + dcache_latency += + TheISA::handleIprWrite(thread->getTC(), &pkt); + } else { + //XXX This needs to be outside of the loop in order to + //work properly for cache line boundary crossing + //accesses in transendian simulations. + data = htog(data); + if (hasPhysMemPort && pkt.getAddr() == physMemAddr) + dcache_latency += physmemPort.sendAtomic(&pkt); + else + dcache_latency += dcachePort.sendAtomic(&pkt); + } + dcache_access = true; + assert(!pkt.isError()); + + if (req->isSwap()) { + assert(res); + *res = pkt.get<T>(); + } } - dcache_access = true; - assert(!pkt.isError()); - if (req->isSwap()) { - assert(res); - *res = pkt.get<T>(); + if (res && !req->isSwap()) { + *res = req->getExtraData(); } } - if (res && !req->isSwap()) { - *res = req->getExtraData(); + // This will need a new way to tell if it's hooked up to a cache or not. + if (req->isUncacheable()) + recordEvent("Uncached Write"); + + //If there's a fault or we don't need to access a second cache line, + //stop now. + if (fault != NoFault || secondAddr <= addr) + { + // If the write needs to have a fault on the access, consider + // calling changeStatus() and changing it to "bad addr write" + // or something. + return fault; } - } - // This will need a new way to tell if it's hooked up to a cache or not. - if (req->isUncacheable()) - recordEvent("Uncached Write"); + /* + * Set up for accessing the second cache line. + */ - // If the write needs to have a fault on the access, consider calling - // changeStatus() and changing it to "bad addr write" or something. - return fault; + //Move the pointer we're reading into to the correct location. + dataPtr += dataSize; + //Adjust the size to get the remaining bytes. + dataSize = addr + sizeof(T) - secondAddr; + //And access the right address. + addr = secondAddr; + } } @@ -545,9 +620,18 @@ AtomicSimpleCPU::tick() preExecute(); - if(curStaticInst) - { + if (curStaticInst) { fault = curStaticInst->execute(this, traceData); + + // keep an instruction count + if (fault == NoFault) + countInst(); + else if (traceData) { + // If there was a fault, we should trace this instruction. + delete traceData; + traceData = NULL; + } + postExecute(); } @@ -604,9 +688,9 @@ AtomicSimpleCPUParams::create() params->cpu_id = cpu_id; params->tracer = tracer; -#if FULL_SYSTEM params->itb = itb; params->dtb = dtb; +#if FULL_SYSTEM params->profile = profile; params->do_quiesce = do_quiesce; params->do_checkpoint_insts = do_checkpoint_insts; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index d2dd52b64..d6b124efc 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -75,7 +75,7 @@ BaseSimpleCPU::BaseSimpleCPU(Params *p) thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); #else thread = new SimpleThread(this, /* thread_num */ 0, p->process, - /* asid */ 0); + p->itb, p->dtb, /* asid */ 0); #endif // !FULL_SYSTEM thread->setStatus(ThreadContext::Unallocated); @@ -357,12 +357,6 @@ BaseSimpleCPU::preExecute() thread->setFloatReg(ZeroReg, 0.0); #endif // ALPHA_ISA - // keep an instruction count - numInst++; - numInsts++; - - thread->funcExeInst++; - // check for instruction-count-based events comInstEventQueue[0]->serviceEvents(numInst); diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 22ffff3b9..2bc329b68 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -100,10 +100,9 @@ class BaseSimpleCPU : public BaseCPU public: struct Params : public BaseCPU::Params { -#if FULL_SYSTEM TheISA::ITB *itb; TheISA::DTB *dtb; -#else +#if !FULL_SYSTEM Process *process; #endif }; @@ -158,6 +157,14 @@ class BaseSimpleCPU : public BaseCPU Counter startNumInst; Stats::Scalar<> numInsts; + void countInst() + { + numInst++; + numInsts++; + + thread->funcExeInst++; + } + virtual Counter totalInstructions() const { return numInst - startNumInst; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 9891efb81..8d1cf9a17 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -540,13 +540,32 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) delete dcache_pkt->req; delete dcache_pkt; dcache_pkt = NULL; + + // keep an instruction count + if (fault == NoFault) + countInst(); + } else if (traceData) { + // If there was a fault, we shouldn't trace this instruction. + delete traceData; + traceData = NULL; } + postExecute(); advanceInst(fault); } } else { // non-memory instruction: execute completely now Fault fault = curStaticInst->execute(this, traceData); + + // keep an instruction count + if (fault == NoFault) + countInst(); + else if (traceData) { + // If there was a fault, we shouldn't trace this instruction. + delete traceData; + traceData = NULL; + } + postExecute(); advanceInst(fault); } @@ -615,6 +634,15 @@ TimingSimpleCPU::completeDataAccess(PacketPtr pkt) Fault fault = curStaticInst->completeAcc(pkt, this, traceData); + // keep an instruction count + if (fault == NoFault) + countInst(); + else if (traceData) { + // If there was a fault, we shouldn't trace this instruction. + delete traceData; + traceData = NULL; + } + if (pkt->isRead() && pkt->isLocked()) { TheISA::handleLockedRead(thread, pkt->req); } @@ -727,9 +755,9 @@ TimingSimpleCPUParams::create() params->cpu_id = cpu_id; params->tracer = tracer; -#if FULL_SYSTEM params->itb = itb; params->dtb = dtb; +#if FULL_SYSTEM params->profile = profile; params->do_quiesce = do_quiesce; params->do_checkpoint_insts = do_checkpoint_insts; diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 191ae2f2e..93772fbe1 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -93,10 +93,10 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, } } #else -SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, - Process *_process, int _asid) +SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, + TheISA::ITB *_itb, TheISA::DTB *_dtb, int _asid) : ThreadState(_cpu, -1, _thread_num, _process, _asid), - cpu(_cpu) + cpu(_cpu), itb(_itb), dtb(_dtb) { regs.clear(); tc = new ProxyThreadContext<SimpleThread>(this); diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 6c6d5f842..1e87b0bb7 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -35,6 +35,7 @@ #include "arch/isa_traits.hh" #include "arch/regfile.hh" #include "arch/syscallreturn.hh" +#include "arch/tlb.hh" #include "config/full_system.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" @@ -49,7 +50,6 @@ class BaseCPU; #if FULL_SYSTEM #include "sim/system.hh" -#include "arch/tlb.hh" class FunctionProfile; class ProfileNode; @@ -109,10 +109,8 @@ class SimpleThread : public ThreadState System *system; -#if FULL_SYSTEM TheISA::ITB *itb; TheISA::DTB *dtb; -#endif // constructor: initialize SimpleThread from given process structure #if FULL_SYSTEM @@ -120,7 +118,8 @@ class SimpleThread : public ThreadState TheISA::ITB *_itb, TheISA::DTB *_dtb, bool use_kernel_stats = true); #else - SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid); + SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, + TheISA::ITB *_itb, TheISA::DTB *_dtb, int _asid); #endif SimpleThread(); @@ -149,10 +148,6 @@ class SimpleThread : public ThreadState */ ThreadContext *getTC() { return tc; } -#if FULL_SYSTEM - int getInstAsid() { return regs.instAsid(); } - int getDataAsid() { return regs.dataAsid(); } - Fault translateInstReq(RequestPtr &req) { return itb->translate(req, tc); @@ -168,27 +163,16 @@ class SimpleThread : public ThreadState return dtb->translate(req, tc, true); } +#if FULL_SYSTEM + int getInstAsid() { return regs.instAsid(); } + int getDataAsid() { return regs.dataAsid(); } + void dumpFuncProfile(); Fault hwrei(); bool simPalCheck(int palFunc); -#else - - Fault translateInstReq(RequestPtr &req) - { - return process->pTable->translate(req); - } - - Fault translateDataReadReq(RequestPtr &req) - { - return process->pTable->translate(req); - } - Fault translateDataWriteReq(RequestPtr &req) - { - return process->pTable->translate(req); - } #endif /******************************************* @@ -199,13 +183,13 @@ class SimpleThread : public ThreadState int getThreadNum() { return tid; } -#if FULL_SYSTEM - System *getSystemPtr() { return system; } - TheISA::ITB *getITBPtr() { return itb; } TheISA::DTB *getDTBPtr() { return dtb; } +#if FULL_SYSTEM + System *getSystemPtr() { return system; } + FunctionalPort *getPhysPort() { return physPort; } /** Return a virtual port. If no thread context is specified then a static diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 3706d8543..1af029093 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -119,13 +119,13 @@ class ThreadContext virtual int readCpuId() = 0; -#if FULL_SYSTEM - virtual System *getSystemPtr() = 0; - virtual TheISA::ITB *getITBPtr() = 0; virtual TheISA::DTB *getDTBPtr() = 0; +#if FULL_SYSTEM + virtual System *getSystemPtr() = 0; + virtual TheISA::Kernel::Statistics *getKernelStats() = 0; virtual FunctionalPort *getPhysPort() = 0; @@ -298,13 +298,13 @@ class ProxyThreadContext : public ThreadContext int readCpuId() { return actualTC->readCpuId(); } -#if FULL_SYSTEM - System *getSystemPtr() { return actualTC->getSystemPtr(); } - TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); } TheISA::DTB *getDTBPtr() { return actualTC->getDTBPtr(); } +#if FULL_SYSTEM + System *getSystemPtr() { return actualTC->getSystemPtr(); } + TheISA::Kernel::Statistics *getKernelStats() { return actualTC->getKernelStats(); } diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc index a00d743cd..efafc3f19 100644 --- a/src/mem/page_table.cc +++ b/src/mem/page_table.cc @@ -63,32 +63,6 @@ PageTable::~PageTable() { } -Fault -PageTable::page_check(Addr addr, int64_t size) const -{ - if (size < sizeof(uint64_t)) { - if (!isPowerOf2(size)) { - panic("Invalid request size!\n"); - return genMachineCheckFault(); - } - - if ((size - 1) & addr) - return genAlignmentFault(); - } - else { - if ((addr & (VMPageSize - 1)) + size > VMPageSize) { - panic("Invalid request size!\n"); - return genMachineCheckFault(); - } - - if ((sizeof(uint64_t) - 1) & addr) - return genAlignmentFault(); - } - - return NoFault; -} - - void PageTable::allocate(Addr vaddr, int64_t size) { @@ -98,62 +72,73 @@ PageTable::allocate(Addr vaddr, int64_t size) DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr+ size); for (; size > 0; size -= pageSize, vaddr += pageSize) { - m5::hash_map<Addr,Addr>::iterator iter = pTable.find(vaddr); + PTableItr iter = pTable.find(vaddr); if (iter != pTable.end()) { // already mapped - fatal("PageTable::allocate: address 0x%x already mapped", vaddr); + fatal("PageTable::allocate: address 0x%x already mapped", + vaddr); } - pTable[vaddr] = system->new_page(); + pTable[vaddr] = TheISA::TlbEntry(system->new_page()); updateCache(vaddr, pTable[vaddr]); } } - - bool -PageTable::translate(Addr vaddr, Addr &paddr) +PageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry) { Addr page_addr = pageAlign(vaddr); - paddr = 0; if (pTableCache[0].vaddr == page_addr) { - paddr = pTableCache[0].paddr + pageOffset(vaddr); + entry = pTableCache[0].entry; return true; } if (pTableCache[1].vaddr == page_addr) { - paddr = pTableCache[1].paddr + pageOffset(vaddr); + entry = pTableCache[1].entry; return true; } if (pTableCache[2].vaddr == page_addr) { - paddr = pTableCache[2].paddr + pageOffset(vaddr); + entry = pTableCache[2].entry; return true; } - m5::hash_map<Addr,Addr>::iterator iter = pTable.find(page_addr); + PTableItr iter = pTable.find(page_addr); if (iter == pTable.end()) { return false; } updateCache(page_addr, iter->second); - paddr = iter->second + pageOffset(vaddr); + entry = iter->second; return true; } +bool +PageTable::translate(Addr vaddr, Addr &paddr) +{ + TheISA::TlbEntry entry; + if (!lookup(vaddr, entry)) + return false; + paddr = pageOffset(vaddr) + entry.pageStart; + return true; +} Fault -PageTable::translate(RequestPtr &req) +PageTable::translate(RequestPtr req) { Addr paddr; assert(pageAlign(req->getVaddr() + req->getSize() - 1) == pageAlign(req->getVaddr())); if (!translate(req->getVaddr(), paddr)) { - return Fault(new PageTableFault(req->getVaddr())); + return Fault(new GenericPageTableFault(req->getVaddr())); } req->setPaddr(paddr); - return page_check(req->getPaddr(), req->getSize()); + if ((paddr & (pageSize - 1)) + req->getSize() > pageSize) { + panic("Request spans page boundaries!\n"); + return NoFault; + } + return NoFault; } void @@ -163,11 +148,11 @@ PageTable::serialize(std::ostream &os) int count = 0; - m5::hash_map<Addr,Addr>::iterator iter = pTable.begin(); - m5::hash_map<Addr,Addr>::iterator end = pTable.end(); + PTableItr iter = pTable.begin(); + PTableItr end = pTable.end(); while (iter != end) { paramOut(os, csprintf("ptable.entry%dvaddr", count), iter->first); - paramOut(os, csprintf("ptable.entry%dpaddr", count), iter->second); + iter->second.serialize(os); ++iter; ++count; @@ -180,16 +165,16 @@ PageTable::unserialize(Checkpoint *cp, const std::string §ion) { int i = 0, count; paramIn(cp, section, "ptable.size", count); - Addr vaddr, paddr; + Addr vaddr; + TheISA::TlbEntry entry; pTable.clear(); while(i < count) { paramIn(cp, section, csprintf("ptable.entry%dvaddr", i), vaddr); - paramIn(cp, section, csprintf("ptable.entry%dpaddr", i), paddr); - pTable[vaddr] = paddr; + entry.unserialize(cp, section); + pTable[vaddr] = entry; ++i; } - } diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh index 64c824238..845bb9112 100644 --- a/src/mem/page_table.hh +++ b/src/mem/page_table.hh @@ -40,11 +40,11 @@ #include "sim/faults.hh" #include "arch/isa_traits.hh" +#include "arch/tlb.hh" #include "base/hashmap.hh" -#include "base/trace.hh" #include "mem/request.hh" -#include "mem/packet.hh" -#include "sim/sim_object.hh" +#include "sim/host.hh" +#include "sim/serialize.hh" class System; @@ -54,12 +54,14 @@ class System; class PageTable { protected: - m5::hash_map<Addr,Addr> pTable; + typedef m5::hash_map<Addr, TheISA::TlbEntry> PTable; + typedef PTable::iterator PTableItr; + PTable pTable; struct cacheElement { - Addr paddr; Addr vaddr; - } ; + TheISA::TlbEntry entry; + }; struct cacheElement pTableCache[3]; @@ -77,11 +79,16 @@ class PageTable Addr pageAlign(Addr a) { return (a & ~offsetMask); } Addr pageOffset(Addr a) { return (a & offsetMask); } - Fault page_check(Addr addr, int64_t size) const; - void allocate(Addr vaddr, int64_t size); /** + * Lookup function + * @param vaddr The virtual address. + * @return entry The page table entry corresponding to vaddr. + */ + bool lookup(Addr vaddr, TheISA::TlbEntry &entry); + + /** * Translate function * @param vaddr The virtual address. * @return Physical address from translation. @@ -90,28 +97,29 @@ class PageTable /** * Perform a translation on the memory request, fills in paddr - * field of mem_req. + * field of req. * @param req The memory request. */ - Fault translate(RequestPtr &req); + Fault translate(RequestPtr req); /** * Update the page table cache. * @param vaddr virtual address (page aligned) to check - * @param paddr physical address (page aligned) to return + * @param pte page table entry to return */ - inline void updateCache(Addr vaddr, Addr paddr) + inline void updateCache(Addr vaddr, TheISA::TlbEntry entry) { - pTableCache[2].paddr = pTableCache[1].paddr; + pTableCache[2].entry = pTableCache[1].entry; pTableCache[2].vaddr = pTableCache[1].vaddr; - pTableCache[1].paddr = pTableCache[0].paddr; + pTableCache[1].entry = pTableCache[0].entry; pTableCache[1].vaddr = pTableCache[0].vaddr; - pTableCache[0].paddr = paddr; + pTableCache[0].entry = entry; pTableCache[0].vaddr = vaddr; } void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); }; diff --git a/src/sim/SConscript b/src/sim/SConscript index bfa0c9a0c..b0af4c795 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -53,6 +53,7 @@ if env['FULL_SYSTEM']: Source('arguments.cc') Source('pseudo_inst.cc') else: + Source('tlb.cc') SimObject('Process.py') Source('process.cc') diff --git a/src/sim/faults.cc b/src/sim/faults.cc index fe62874d7..6d6a8b5f6 100644 --- a/src/sim/faults.cc +++ b/src/sim/faults.cc @@ -56,8 +56,9 @@ void UnimpFault::invoke(ThreadContext * tc) { panic("Unimpfault: %s\n", panicStr.c_str()); } + #if !FULL_SYSTEM -void PageTableFault::invoke(ThreadContext *tc) +void GenericPageTableFault::invoke(ThreadContext *tc) { Process *p = tc->getProcessPtr(); @@ -65,4 +66,9 @@ void PageTableFault::invoke(ThreadContext *tc) panic("Page table fault when accessing virtual address %#x\n", vaddr); } + +void GenericAlignmentFault::invoke(ThreadContext *tc) +{ + panic("Alignment fault when accessing virtual address %#x\n", vaddr); +} #endif diff --git a/src/sim/faults.hh b/src/sim/faults.hh index f2e638945..cfc6ad105 100644 --- a/src/sim/faults.hh +++ b/src/sim/faults.hh @@ -77,13 +77,23 @@ class UnimpFault : public FaultBase }; #if !FULL_SYSTEM -class PageTableFault : public FaultBase +class GenericPageTableFault : public FaultBase { private: Addr vaddr; public: - FaultName name() const {return "M5 page table fault";} - PageTableFault(Addr va) : vaddr(va) {} + FaultName name() const {return "Generic page table fault";} + GenericPageTableFault(Addr va) : vaddr(va) {} + void invoke(ThreadContext * tc); +}; + +class GenericAlignmentFault : public FaultBase +{ + private: + Addr vaddr; + public: + FaultName name() const {return "Generic alignment fault";} + GenericAlignmentFault(Addr va) : vaddr(va) {} void invoke(ThreadContext * tc); }; #endif diff --git a/src/sim/process.cc b/src/sim/process.cc index 7343039df..1e6395d55 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -90,6 +90,7 @@ Process::Process(const string &nm, int stderr_fd) : SimObject(nm), system(_system) { + M5_pid = system->allocatePID(); // initialize first 3 fds (stdin, stdout, stderr) fd_map[STDIN_FILENO] = stdin_fd; fd_map[STDOUT_FILENO] = stdout_fd; diff --git a/src/sim/process.hh b/src/sim/process.hh index 8c702da60..83c00a676 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -137,6 +137,10 @@ class Process : public SimObject public: PageTable *pTable; + //This id is assigned by m5 and is used to keep process' tlb entries + //separated. + uint64_t M5_pid; + private: // file descriptor remapping support static const int MAX_FD = 256; // max legal fd value diff --git a/src/sim/system.cc b/src/sim/system.cc index eb0655aa5..512d4bdb5 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -64,6 +64,7 @@ System::System(Params *p) virtPort(p->name + "-vport"), #else page_ptr(0), + next_PID(0), #endif memoryMode(p->mem_mode), _params(p) { diff --git a/src/sim/system.hh b/src/sim/system.hh index 197d9027b..cdd5bebb0 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -125,6 +125,15 @@ class System : public SimObject int page_ptr; + protected: + uint64_t next_PID; + + public: + uint64_t allocatePID() + { + return next_PID++; + } + #endif // FULL_SYSTEM diff --git a/src/sim/tlb.cc b/src/sim/tlb.cc new file mode 100644 index 000000000..5ceec637e --- /dev/null +++ b/src/sim/tlb.cc @@ -0,0 +1,50 @@ +/* + * 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. + * + * Authors: Gabe Black + */ + +#include "cpu/thread_context.hh" +#include "mem/page_table.hh" +#include "sim/process.hh" +#include "sim/tlb.hh" + +Fault +GenericTLBBase::translate(RequestPtr req, ThreadContext * tc) +{ +#if FULL_SYSTEM + panic("Generic translation shouldn't be used in full system mode.\n"); +#else + Process * p = tc->getProcessPtr(); + + Fault fault = p->pTable->translate(req); + if(fault != NoFault) + return fault; + + return NoFault; +#endif +} diff --git a/src/sim/tlb.hh b/src/sim/tlb.hh new file mode 100644 index 000000000..c4c171015 --- /dev/null +++ b/src/sim/tlb.hh @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2006 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. + * + * Authors: Gabe Black + */ + +#ifndef __SIM_TLB_HH__ +#define __SIM_TLB_HH__ + +#include "base/misc.hh" +#include "mem/request.hh" +#include "sim/faults.hh" +#include "sim/sim_object.hh" + +class ThreadContext; +class Packet; + +class GenericTLBBase : public SimObject +{ + protected: + GenericTLBBase(const std::string &name) : SimObject(name) + {} + + Fault translate(RequestPtr req, ThreadContext *tc); +}; + +template <bool doSizeCheck=true, bool doAlignmentCheck=true> +class GenericTLB : public GenericTLBBase +{ + public: + GenericTLB(const std::string &name) : GenericTLBBase(name) + {} + + Fault translate(RequestPtr req, ThreadContext *tc, bool=false) + { + Fault fault = GenericTLBBase::translate(req, tc); + if (fault != NoFault) + return fault; + + typeof(req->getSize()) size = req->getSize(); + Addr paddr = req->getPaddr(); + + if(doSizeCheck && !isPowerOf2(size)) + panic("Invalid request size!\n"); + if (doAlignmentCheck && ((size - 1) & paddr)) + return new GenericAlignmentFault(paddr); + + return NoFault; + } +}; + +template <bool doSizeCheck=true, bool doAlignmentCheck=true> +class GenericITB : public GenericTLB<doSizeCheck, doAlignmentCheck> +{ + public: + GenericITB(const std::string &name) : + GenericTLB<doSizeCheck, doAlignmentCheck>(name) + {} +}; + +template <bool doSizeCheck=true, bool doAlignmentCheck=true> +class GenericDTB : public GenericTLB<doSizeCheck, doAlignmentCheck> +{ + public: + GenericDTB(const std::string &name) : + GenericTLB<doSizeCheck, doAlignmentCheck>(name) + {} +}; + +#endif // __ARCH_SPARC_TLB_HH__ |