diff options
Diffstat (limited to 'src/arch/alpha')
37 files changed, 3183 insertions, 1165 deletions
diff --git a/src/arch/alpha/SConscript b/src/arch/alpha/SConscript index 216c88cc7..3cc5ec270 100644 --- a/src/arch/alpha/SConscript +++ b/src/arch/alpha/SConscript @@ -48,21 +48,29 @@ Import('env') # Base sources used by all configurations. base_sources = Split(''' faults.cc - isa_traits.cc + floatregfile.cc + intregfile.cc + miscregfile.cc + regfile.cc ''') # Full-system sources full_system_sources = Split(''' - tlb.cc arguments.cc ev5.cc + freebsd/system.cc + idle_event.cc + ipr.cc + kernel_stats.cc + linux/system.cc osfpal.cc + pagetable.cc stacktrace.cc - vtophys.cc + remote_gdb.cc system.cc - freebsd/system.cc - linux/system.cc + tlb.cc tru64/system.cc + vtophys.cc ''') diff --git a/src/arch/alpha/arguments.cc b/src/arch/alpha/arguments.cc index 9f9002003..e89bd70b0 100644 --- a/src/arch/alpha/arguments.cc +++ b/src/arch/alpha/arguments.cc @@ -35,7 +35,7 @@ using namespace AlphaISA; -AlphaArguments::Data::~Data() +Arguments::Data::~Data() { while (!data.empty()) { delete [] data.front(); @@ -44,7 +44,7 @@ AlphaArguments::Data::~Data() } char * -AlphaArguments::Data::alloc(size_t size) +Arguments::Data::alloc(size_t size) { char *buf = new char[size]; data.push_back(buf); @@ -52,7 +52,7 @@ AlphaArguments::Data::alloc(size_t size) } uint64_t -AlphaArguments::getArg(bool fp) +Arguments::getArg(bool fp) { if (number < 6) { if (fp) diff --git a/src/arch/alpha/arguments.hh b/src/arch/alpha/arguments.hh index d977d48d6..c44181a8d 100644 --- a/src/arch/alpha/arguments.hh +++ b/src/arch/alpha/arguments.hh @@ -41,7 +41,7 @@ class ThreadContext; namespace AlphaISA { -class AlphaArguments +class Arguments { protected: ThreadContext *tc; @@ -65,62 +65,62 @@ class AlphaArguments RefCountingPtr<Data> data; public: - AlphaArguments(ThreadContext *ctx, int n = 0) + Arguments(ThreadContext *ctx, int n = 0) : tc(ctx), number(n), data(NULL) { assert(number >= 0); data = new Data;} - AlphaArguments(const AlphaArguments &args) + Arguments(const Arguments &args) : tc(args.tc), number(args.number), data(args.data) {} - ~AlphaArguments() {} + ~Arguments() {} ThreadContext *getThreadContext() const { return tc; } - const AlphaArguments &operator=(const AlphaArguments &args) { + const Arguments &operator=(const Arguments &args) { tc = args.tc; number = args.number; data = args.data; return *this; } - AlphaArguments &operator++() { + Arguments &operator++() { ++number; assert(number >= 0); return *this; } - AlphaArguments operator++(int) { - AlphaArguments args = *this; + Arguments operator++(int) { + Arguments args = *this; ++number; assert(number >= 0); return args; } - AlphaArguments &operator--() { + Arguments &operator--() { --number; assert(number >= 0); return *this; } - AlphaArguments operator--(int) { - AlphaArguments args = *this; + Arguments operator--(int) { + Arguments args = *this; --number; assert(number >= 0); return args; } - const AlphaArguments &operator+=(int index) { + const Arguments &operator+=(int index) { number += index; assert(number >= 0); return *this; } - const AlphaArguments &operator-=(int index) { + const Arguments &operator-=(int index) { number -= index; assert(number >= 0); return *this; } - AlphaArguments operator[](int index) { - return AlphaArguments(tc, index); + Arguments operator[](int index) { + return Arguments(tc, index); } template <class T> diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 7595423c3..3d71fbda5 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -31,16 +31,16 @@ #include "arch/alpha/faults.hh" #include "arch/alpha/isa_traits.hh" +#include "arch/alpha/kernel_stats.hh" #include "arch/alpha/osfpal.hh" #include "arch/alpha/tlb.hh" -#include "base/kgdb.h" +#include "arch/alpha/kgdb.h" #include "base/remote_gdb.hh" #include "base/stats/events.hh" #include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" -#include "kern/kernel_stats.hh" #include "sim/debug.hh" #include "sim/sim_exit.hh" @@ -60,7 +60,7 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId) tc->setIntReg(16, cpuId); tc->setIntReg(0, cpuId); - AlphaFault *reset = new ResetFault; + AlphaISA::AlphaFault *reset = new AlphaISA::ResetFault; tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + reset->vect()); tc->setNextPC(tc->readPC() + sizeof(MachInst)); @@ -147,7 +147,7 @@ AlphaISA::zeroRegisters(CPU *cpu) Fault SimpleThread::hwrei() { - if (!inPalMode()) + if (!(readPC() & 0x3)) return new UnimplementedOpcodeFault; setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR)); @@ -176,7 +176,7 @@ AlphaISA::MiscRegFile::getDataAsid() } AlphaISA::MiscReg -AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ThreadContext *tc) +AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc) { uint64_t retval = 0; // return value, default 0 @@ -269,12 +269,12 @@ AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ThreadContext *tc) case AlphaISA::IPR_DTB_IAP: case AlphaISA::IPR_ITB_IA: case AlphaISA::IPR_ITB_IAP: - fault = new UnimplementedOpcodeFault; + panic("Tried to read write only register %d\n", idx); break; default: // invalid IPR - fault = new UnimplementedOpcodeFault; + panic("Tried to read from invalid ipr %d\n", idx); break; } @@ -286,13 +286,13 @@ AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ThreadContext *tc) int break_ipl = -1; #endif -Fault +void AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) { uint64_t old; if (tc->misspeculating()) - return NoFault; + return; switch (idx) { case AlphaISA::IPR_PALtemp0: @@ -379,10 +379,10 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) case AlphaISA::IPR_DTB_CM: if (val & 0x18) { if (tc->getKernelStats()) - tc->getKernelStats()->mode(Kernel::user, tc); + tc->getKernelStats()->mode(TheISA::Kernel::user, tc); } else { if (tc->getKernelStats()) - tc->getKernelStats()->mode(Kernel::kernel, tc); + tc->getKernelStats()->mode(TheISA::Kernel::kernel, tc); } case AlphaISA::IPR_ICM: @@ -443,7 +443,7 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) case AlphaISA::IPR_ITB_PTE_TEMP: case AlphaISA::IPR_DTB_PTE_TEMP: // read-only registers - return new UnimplementedOpcodeFault; + panic("Tried to write read only ipr %d\n", idx); case AlphaISA::IPR_HWINT_CLR: case AlphaISA::IPR_SL_XMIT: @@ -547,18 +547,17 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) default: // invalid IPR - return new UnimplementedOpcodeFault; + panic("Tried to write to invalid ipr %d\n", idx); } // no error... - return NoFault; } void AlphaISA::copyIprs(ThreadContext *src, ThreadContext *dest) { - for (int i = IPR_Base_DepTag; i < NumInternalProcRegs; ++i) { + for (int i = 0; i < NumInternalProcRegs; ++i) { dest->setMiscReg(i, src->readMiscReg(i)); } } diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index 7179bf025..5efcf92e4 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -125,7 +125,7 @@ void AlphaFault::invoke(ThreadContext * tc) countStat()++; // exception restart address - if (setRestartAddress() || !tc->inPalMode()) + if (setRestartAddress() || !(tc->readPC() & 0x3)) tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->readPC()); if (skipFaultingInstruction()) { diff --git a/src/arch/alpha/floatregfile.cc b/src/arch/alpha/floatregfile.cc new file mode 100644 index 000000000..512b0df95 --- /dev/null +++ b/src/arch/alpha/floatregfile.cc @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2003-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: Steve Reinhardt + * Gabe Black + * Kevin Lim + */ + +#include "arch/alpha/floatregfile.hh" +#include "sim/serialize.hh" + +namespace AlphaISA +{ + void + FloatRegFile::serialize(std::ostream &os) + { + SERIALIZE_ARRAY(q, NumFloatRegs); + } + + void + FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ARRAY(q, NumFloatRegs); + } +} diff --git a/src/arch/alpha/floatregfile.hh b/src/arch/alpha/floatregfile.hh new file mode 100644 index 000000000..d289f5785 --- /dev/null +++ b/src/arch/alpha/floatregfile.hh @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003-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: Steve Reinhardt + * Gabe Black + */ + +#ifndef __ARCH_ALPHA_FLOATREGFILE_HH__ +#define __ARCH_ALPHA_FLOATREGFILE_HH__ + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/types.hh" + +#include <string.h> +#include <iostream> + +class Checkpoint; + +namespace AlphaISA +{ + static inline std::string getFloatRegName(RegIndex) + { + return ""; + } + + class FloatRegFile + { + public: + + union { + uint64_t q[NumFloatRegs]; // integer qword view + double d[NumFloatRegs]; // double-precision floating point view + }; + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + + void clear() + { bzero(d, sizeof(d)); } + }; +} + +#endif diff --git a/src/arch/alpha/idle_event.cc b/src/arch/alpha/idle_event.cc new file mode 100644 index 000000000..0f6806319 --- /dev/null +++ b/src/arch/alpha/idle_event.cc @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2004-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: Lisa Hsu + * Nathan Binkert + */ + +#include "arch/alpha/idle_event.hh" +#include "arch/alpha/kernel_stats.hh" +#include "cpu/thread_context.hh" + +using namespace TheISA; + +void +IdleStartEvent::process(ThreadContext *tc) +{ + if (tc->getKernelStats()) + tc->getKernelStats()->setIdleProcess( + tc->readMiscReg(AlphaISA::IPR_PALtemp23), tc); + remove(); +} diff --git a/src/arch/alpha/idle_event.hh b/src/arch/alpha/idle_event.hh new file mode 100644 index 000000000..97d5bdd6e --- /dev/null +++ b/src/arch/alpha/idle_event.hh @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-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: Nathan Binkert + * Lisa Hsu + * Ali Saidi + */ + +#ifndef __KERN_ALPHA_IDLE_EVENT_HH__ +#define __KERN_ALPHA_IDLE_EVENT_HH__ + +#include "cpu/pc_event.hh" + +class IdleStartEvent : public PCEvent +{ + public: + IdleStartEvent(PCEventQueue *q, const std::string &desc, Addr addr) + : PCEvent(q, desc, addr) + {} + virtual void process(ThreadContext *tc); +}; + +#endif // __KERN_ALPHA_IDLE_EVENT_HH__ diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh new file mode 100644 index 000000000..75031ae47 --- /dev/null +++ b/src/arch/alpha/interrupts.hh @@ -0,0 +1,166 @@ +/* + * 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: Steve Reinhardt + * Kevin Lim + */ + +#ifndef __ARCH_ALPHA_INTERRUPT_HH__ +#define __ARCH_ALPHA_INTERRUPT_HH__ + +#include "arch/alpha/faults.hh" +#include "arch/alpha/isa_traits.hh" +#include "cpu/thread_context.hh" + +namespace AlphaISA +{ + class Interrupts + { + protected: + uint64_t interrupts[NumInterruptLevels]; + uint64_t intstatus; + + public: + Interrupts() + { + memset(interrupts, 0, sizeof(interrupts)); + intstatus = 0; + } + + void post(int int_num, int index) + { + DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); + + if (int_num < 0 || int_num >= NumInterruptLevels) + panic("int_num out of bounds\n"); + + if (index < 0 || index >= sizeof(uint64_t) * 8) + panic("int_num out of bounds\n"); + + interrupts[int_num] |= 1 << index; + intstatus |= (ULL(1) << int_num); + } + + void clear(int int_num, int index) + { + DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); + + if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) + panic("int_num out of bounds\n"); + + if (index < 0 || index >= sizeof(uint64_t) * 8) + panic("int_num out of bounds\n"); + + interrupts[int_num] &= ~(1 << index); + if (interrupts[int_num] == 0) + intstatus &= ~(ULL(1) << int_num); + } + + void clear_all() + { + DPRINTF(Interrupt, "Interrupts all cleared\n"); + + memset(interrupts, 0, sizeof(interrupts)); + intstatus = 0; + } + + void serialize(std::ostream &os) + { + SERIALIZE_ARRAY(interrupts, NumInterruptLevels); + SERIALIZE_SCALAR(intstatus); + } + + void unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); + UNSERIALIZE_SCALAR(intstatus); + } + + bool check_interrupts(ThreadContext * tc) const + { + return (intstatus != 0) && !(tc->readPC() & 0x3); + } + + Fault getInterrupt(ThreadContext * tc) + { + int ipl = 0; + int summary = 0; + + if (tc->readMiscReg(IPR_ASTRR)) + panic("asynchronous traps not implemented\n"); + + if (tc->readMiscReg(IPR_SIRR)) { + for (int i = INTLEVEL_SOFTWARE_MIN; + i < INTLEVEL_SOFTWARE_MAX; i++) { + if (tc->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { + // See table 4-19 of 21164 hardware reference + ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; + summary |= (ULL(1) << i); + } + } + } + + uint64_t interrupts = intstatus; + if (interrupts) { + for (int i = INTLEVEL_EXTERNAL_MIN; + i < INTLEVEL_EXTERNAL_MAX; i++) { + if (interrupts & (ULL(1) << i)) { + // See table 4-19 of 21164 hardware reference + ipl = i; + summary |= (ULL(1) << i); + } + } + } + + if (ipl && ipl > tc->readMiscReg(IPR_IPLR)) { + tc->setMiscReg(IPR_ISR, summary); + tc->setMiscReg(IPR_INTID, ipl); + + /* The following needs to be added back in somehow */ + // Checker needs to know these two registers were updated. +/*#if USE_CHECKER + if (this->checker) { + this->checker->threadBase()->setMiscReg(IPR_ISR, summary); + this->checker->threadBase()->setMiscReg(IPR_INTID, ipl); + } +#endif*/ + + DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", + tc->readMiscReg(IPR_IPLR), ipl, summary); + + return new InterruptFault; + } else { + return NoFault; + } + } + + private: + }; +} + +#endif + diff --git a/src/arch/alpha/intregfile.cc b/src/arch/alpha/intregfile.cc new file mode 100644 index 000000000..0188cb2cd --- /dev/null +++ b/src/arch/alpha/intregfile.cc @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2003-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: Steve Reinhardt + * Gabe Black + * Kevin Lim + */ + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/intregfile.hh" +#include "sim/serialize.hh" + +namespace AlphaISA +{ +#if FULL_SYSTEM + const int reg_redir[AlphaISA::NumIntRegs] = { + /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, + /* 8 */ 32, 33, 34, 35, 36, 37, 38, 15, + /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, + /* 24 */ 24, 39, 26, 27, 28, 29, 30, 31 }; +#else + const int reg_redir[AlphaISA::NumIntRegs] = { + /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, + /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, + /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, + /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31 }; +#endif + + void + IntRegFile::serialize(std::ostream &os) + { + SERIALIZE_ARRAY(regs, NumIntRegs); + } + + void + IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ARRAY(regs, NumIntRegs); + } +} + diff --git a/src/arch/alpha/intregfile.hh b/src/arch/alpha/intregfile.hh new file mode 100644 index 000000000..0d65f69e0 --- /dev/null +++ b/src/arch/alpha/intregfile.hh @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2003-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: Steve Reinhardt + * Gabe Black + */ + +#ifndef __ARCH_ALPHA_INTREGFILE_HH__ +#define __ARCH_ALPHA_INTREGFILE_HH__ + +#include "arch/alpha/types.hh" + +#include <iostream> +#include <strings.h> + +class Checkpoint; + +namespace AlphaISA +{ + static inline std::string getIntRegName(RegIndex) + { + return ""; + } + + // redirected register map, really only used for the full system case. + extern const int reg_redir[NumIntRegs]; + + class IntRegFile + { + protected: + IntReg regs[NumIntRegs]; + + public: + + IntReg readReg(int intReg) + { + return regs[intReg]; + } + + void setReg(int intReg, const IntReg &val) + { + regs[intReg] = val; + } + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + + void clear() + { bzero(regs, sizeof(regs)); } + }; +} + +#endif diff --git a/src/arch/alpha/ipr.cc b/src/arch/alpha/ipr.cc new file mode 100644 index 000000000..8e83102eb --- /dev/null +++ b/src/arch/alpha/ipr.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2003-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 <assert.h> +#include <string.h> + +#include "arch/alpha/ipr.hh" + +namespace AlphaISA +{ + md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs] = + { + //Write only + RAW_IPR_HWINT_CLR, // H/W interrupt clear register + RAW_IPR_SL_XMIT, // serial line transmit register + RAW_IPR_DC_FLUSH, + RAW_IPR_IC_FLUSH, // instruction cache flush control + RAW_IPR_ALT_MODE, // alternate mode register + RAW_IPR_DTB_IA, // DTLB invalidate all register + RAW_IPR_DTB_IAP, // DTLB invalidate all process register + RAW_IPR_ITB_IA, // ITLB invalidate all register + RAW_IPR_ITB_IAP, // ITLB invalidate all process register + + //Read only + RAW_IPR_INTID, // interrupt ID register + RAW_IPR_SL_RCV, // serial line receive register + RAW_IPR_MM_STAT, // data MMU fault status register + RAW_IPR_ITB_PTE_TEMP, // ITLB page table entry temp register + RAW_IPR_DTB_PTE_TEMP, // DTLB page table entry temporary register + + RAW_IPR_ISR, // interrupt summary register + RAW_IPR_ITB_TAG, // ITLB tag register + RAW_IPR_ITB_PTE, // ITLB page table entry register + RAW_IPR_ITB_ASN, // ITLB address space register + RAW_IPR_ITB_IS, // ITLB invalidate select register + RAW_IPR_SIRR, // software interrupt request register + RAW_IPR_ASTRR, // asynchronous system trap request register + RAW_IPR_ASTER, // asynchronous system trap enable register + RAW_IPR_EXC_ADDR, // exception address register + RAW_IPR_EXC_SUM, // exception summary register + RAW_IPR_EXC_MASK, // exception mask register + RAW_IPR_PAL_BASE, // PAL base address register + RAW_IPR_ICM, // instruction current mode + RAW_IPR_IPLR, // interrupt priority level register + RAW_IPR_IFAULT_VA_FORM, // formatted faulting virtual addr register + RAW_IPR_IVPTBR, // virtual page table base register + RAW_IPR_ICSR, // instruction control and status register + RAW_IPR_IC_PERR_STAT, // inst cache parity error status register + RAW_IPR_PMCTR, // performance counter register + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + RAW_IPR_PALtemp0, // local scratch + RAW_IPR_PALtemp1, // local scratch + RAW_IPR_PALtemp2, // entUna + RAW_IPR_PALtemp3, // CPU specific impure area pointer + RAW_IPR_PALtemp4, // memory management temp + RAW_IPR_PALtemp5, // memory management temp + RAW_IPR_PALtemp6, // memory management temp + RAW_IPR_PALtemp7, // entIF + RAW_IPR_PALtemp8, // intmask + RAW_IPR_PALtemp9, // entSys + RAW_IPR_PALtemp10, // ?? + RAW_IPR_PALtemp11, // entInt + RAW_IPR_PALtemp12, // entArith + RAW_IPR_PALtemp13, // reserved for platform specific PAL + RAW_IPR_PALtemp14, // reserved for platform specific PAL + RAW_IPR_PALtemp15, // reserved for platform specific PAL + RAW_IPR_PALtemp16, // scratch / whami<7:0> / mces<4:0> + RAW_IPR_PALtemp17, // sysval + RAW_IPR_PALtemp18, // usp + RAW_IPR_PALtemp19, // ksp + RAW_IPR_PALtemp20, // PTBR + RAW_IPR_PALtemp21, // entMM + RAW_IPR_PALtemp22, // kgp + RAW_IPR_PALtemp23, // PCBB + + RAW_IPR_DTB_ASN, // DTLB address space number register + RAW_IPR_DTB_CM, // DTLB current mode register + RAW_IPR_DTB_TAG, // DTLB tag register + RAW_IPR_DTB_PTE, // DTLB page table entry register + + RAW_IPR_VA, // fault virtual address register + RAW_IPR_VA_FORM, // formatted virtual address register + RAW_IPR_MVPTBR, // MTU virtual page table base register + RAW_IPR_DTB_IS, // DTLB invalidate single register + RAW_IPR_CC, // cycle counter register + RAW_IPR_CC_CTL, // cycle counter control register + RAW_IPR_MCSR, // MTU control register + + RAW_IPR_DC_PERR_STAT, // Dcache parity error status register + RAW_IPR_DC_TEST_CTL, // Dcache test tag control register + RAW_IPR_DC_TEST_TAG, // Dcache test tag register + RAW_IPR_DC_TEST_TAG_TEMP, // Dcache test tag temporary register + RAW_IPR_DC_MODE, // Dcache mode register + RAW_IPR_MAF_MODE // miss address file mode register + }; + + int IprToMiscRegIndex[MaxInternalProcRegs]; + + void initializeIprTable() + { + static bool initialized = false; + if(initialized) + return; + + memset(IprToMiscRegIndex, -1, MaxInternalProcRegs * sizeof(int)); + + for(int x = 0; x < NumInternalProcRegs; x++) + IprToMiscRegIndex[MiscRegIndexToIpr[x]] = x; + } +} + diff --git a/src/arch/alpha/ipr.hh b/src/arch/alpha/ipr.hh new file mode 100644 index 000000000..b55154764 --- /dev/null +++ b/src/arch/alpha/ipr.hh @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2003-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: Steve Reinhardt + * Gabe Black + */ + +#ifndef __ARCH_ALPHA_IPR_HH__ +#define __ARCH_ALPHA_IPR_HH__ + +namespace AlphaISA +{ + //////////////////////////////////////////////////////////////////////// + // + // Internal Processor Reigsters + // + enum md_ipr_names + { + RAW_IPR_ISR = 0x100, // interrupt summary register + RAW_IPR_ITB_TAG = 0x101, // ITLB tag register + RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry register + RAW_IPR_ITB_ASN = 0x103, // ITLB address space register + RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register + RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all register + RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process register + RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select register + RAW_IPR_SIRR = 0x108, // software interrupt request register + RAW_IPR_ASTRR = 0x109, // asynchronous system trap request register + RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable register + RAW_IPR_EXC_ADDR = 0x10b, // exception address register + RAW_IPR_EXC_SUM = 0x10c, // exception summary register + RAW_IPR_EXC_MASK = 0x10d, // exception mask register + RAW_IPR_PAL_BASE = 0x10e, // PAL base address register + RAW_IPR_ICM = 0x10f, // instruction current mode + RAW_IPR_IPLR = 0x110, // interrupt priority level register + RAW_IPR_INTID = 0x111, // interrupt ID register + RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register + RAW_IPR_IVPTBR = 0x113, // virtual page table base register + RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear register + RAW_IPR_SL_XMIT = 0x116, // serial line transmit register + RAW_IPR_SL_RCV = 0x117, // serial line receive register + RAW_IPR_ICSR = 0x118, // instruction control and status register + RAW_IPR_IC_FLUSH = 0x119, // instruction cache flush control + RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register + RAW_IPR_PMCTR = 0x11c, // performance counter register + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + RAW_IPR_PALtemp0 = 0x140, // local scratch + RAW_IPR_PALtemp1 = 0x141, // local scratch + RAW_IPR_PALtemp2 = 0x142, // entUna + RAW_IPR_PALtemp3 = 0x143, // CPU specific impure area pointer + RAW_IPR_PALtemp4 = 0x144, // memory management temp + RAW_IPR_PALtemp5 = 0x145, // memory management temp + RAW_IPR_PALtemp6 = 0x146, // memory management temp + RAW_IPR_PALtemp7 = 0x147, // entIF + RAW_IPR_PALtemp8 = 0x148, // intmask + RAW_IPR_PALtemp9 = 0x149, // entSys + RAW_IPR_PALtemp10 = 0x14a, // ?? + RAW_IPR_PALtemp11 = 0x14b, // entInt + RAW_IPR_PALtemp12 = 0x14c, // entArith + RAW_IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL + RAW_IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL + RAW_IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL + RAW_IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0> + RAW_IPR_PALtemp17 = 0x151, // sysval + RAW_IPR_PALtemp18 = 0x152, // usp + RAW_IPR_PALtemp19 = 0x153, // ksp + RAW_IPR_PALtemp20 = 0x154, // PTBR + RAW_IPR_PALtemp21 = 0x155, // entMM + RAW_IPR_PALtemp22 = 0x156, // kgp + RAW_IPR_PALtemp23 = 0x157, // PCBB + + RAW_IPR_DTB_ASN = 0x200, // DTLB address space number register + RAW_IPR_DTB_CM = 0x201, // DTLB current mode register + RAW_IPR_DTB_TAG = 0x202, // DTLB tag register + RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry register + RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register + + RAW_IPR_MM_STAT = 0x205, // data MMU fault status register + RAW_IPR_VA = 0x206, // fault virtual address register + RAW_IPR_VA_FORM = 0x207, // formatted virtual address register + RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base register + RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process register + RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all register + RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single register + RAW_IPR_ALT_MODE = 0x20c, // alternate mode register + RAW_IPR_CC = 0x20d, // cycle counter register + RAW_IPR_CC_CTL = 0x20e, // cycle counter control register + RAW_IPR_MCSR = 0x20f, // MTU control register + + RAW_IPR_DC_FLUSH = 0x210, + RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register + RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register + RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag register + RAW_IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register + RAW_IPR_DC_MODE = 0x216, // Dcache mode register + RAW_IPR_MAF_MODE = 0x217, // miss address file mode register + + MaxInternalProcRegs // number of IPR registers + }; + + enum MiscRegIpr + { + //Write only + MinWriteOnlyIpr, + IPR_HWINT_CLR = MinWriteOnlyIpr, + IPR_SL_XMIT, + IPR_DC_FLUSH, + IPR_IC_FLUSH, + IPR_ALT_MODE, + IPR_DTB_IA, + IPR_DTB_IAP, + IPR_ITB_IA, + MaxWriteOnlyIpr, + IPR_ITB_IAP = MaxWriteOnlyIpr, + + //Read only + MinReadOnlyIpr, + IPR_INTID = MinReadOnlyIpr, + IPR_SL_RCV, + IPR_MM_STAT, + IPR_ITB_PTE_TEMP, + MaxReadOnlyIpr, + IPR_DTB_PTE_TEMP = MaxReadOnlyIpr, + + IPR_ISR, + IPR_ITB_TAG, + IPR_ITB_PTE, + IPR_ITB_ASN, + IPR_ITB_IS, + IPR_SIRR, + IPR_ASTRR, + IPR_ASTER, + IPR_EXC_ADDR, + IPR_EXC_SUM, + IPR_EXC_MASK, + IPR_PAL_BASE, + IPR_ICM, + IPR_IPLR, + IPR_IFAULT_VA_FORM, + IPR_IVPTBR, + IPR_ICSR, + IPR_IC_PERR_STAT, + IPR_PMCTR, + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + IPR_PALtemp0, + IPR_PALtemp1, + IPR_PALtemp2, + IPR_PALtemp3, + IPR_PALtemp4, + IPR_PALtemp5, + IPR_PALtemp6, + IPR_PALtemp7, + IPR_PALtemp8, + IPR_PALtemp9, + IPR_PALtemp10, + IPR_PALtemp11, + IPR_PALtemp12, + IPR_PALtemp13, + IPR_PALtemp14, + IPR_PALtemp15, + IPR_PALtemp16, + IPR_PALtemp17, + IPR_PALtemp18, + IPR_PALtemp19, + IPR_PALtemp20, + IPR_PALtemp21, + IPR_PALtemp22, + IPR_PALtemp23, + + IPR_DTB_ASN, + IPR_DTB_CM, + IPR_DTB_TAG, + IPR_DTB_PTE, + + IPR_VA, + IPR_VA_FORM, + IPR_MVPTBR, + IPR_DTB_IS, + IPR_CC, + IPR_CC_CTL, + IPR_MCSR, + + IPR_DC_PERR_STAT, + IPR_DC_TEST_CTL, + IPR_DC_TEST_TAG, + IPR_DC_TEST_TAG_TEMP, + IPR_DC_MODE, + IPR_MAF_MODE, + + NumInternalProcRegs // number of IPR registers + }; + + inline bool IprIsWritable(int index) + { + return index < MinReadOnlyIpr || index > MaxReadOnlyIpr; + } + + inline bool IprIsReadable(int index) + { + return index < MinWriteOnlyIpr || index > MaxWriteOnlyIpr; + } + + extern md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs]; + extern int IprToMiscRegIndex[MaxInternalProcRegs]; + + void initializeIprTable(); +} + +#endif diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 5bd19b677..7014d4c22 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -629,7 +629,7 @@ decode OPCODE default Unknown::unknown() { /* Rb is a fake dependency so here is a fun way to get * the parser to understand that. */ - Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC, fault) + (Rb & 0); + Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC) + (Rb & 0); #else Ra = curTick; @@ -661,12 +661,12 @@ decode OPCODE default Unknown::unknown() { #if FULL_SYSTEM format BasicOperate { 0xe000: rc({{ - Ra = xc->readIntrFlag(); - xc->setIntrFlag(0); + Ra = IntrFlag; + IntrFlag = 0; }}, IsNonSpeculative, IsUnverifiable); 0xf000: rs({{ - Ra = xc->readIntrFlag(); - xc->setIntrFlag(1); + Ra = IntrFlag; + IntrFlag = 1; }}, IsNonSpeculative, IsUnverifiable); } #else @@ -681,7 +681,7 @@ decode OPCODE default Unknown::unknown() { 0x00: CallPal::call_pal({{ if (!palValid || (palPriv - && xc->readMiscRegWithEffect(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) { + && xc->readMiscRegWithEffect(AlphaISA::IPR_ICM) != AlphaISA::mode_kernel)) { // invalid pal function code, or attempt to do privileged // PAL call in non-kernel mode fault = new UnimplementedOpcodeFault; @@ -693,7 +693,7 @@ decode OPCODE default Unknown::unknown() { if (dopal) { xc->setMiscRegWithEffect(AlphaISA::IPR_EXC_ADDR, NPC); - NPC = xc->readMiscRegWithEffect(AlphaISA::IPR_PAL_BASE, fault) + palOffset; + NPC = xc->readMiscRegWithEffect(AlphaISA::IPR_PAL_BASE) + palOffset; } } }}, IsNonSpeculative); @@ -745,7 +745,13 @@ decode OPCODE default Unknown::unknown() { 0: OpcdecFault::hw_mfpr(); format HwMoveIPR { 1: hw_mfpr({{ - Ra = xc->readMiscRegWithEffect(ipr_index, fault); + int miscRegIndex = (ipr_index < MaxInternalProcRegs) ? + IprToMiscRegIndex[ipr_index] : -1; + if(miscRegIndex < 0 || !IprIsReadable(miscRegIndex) || + miscRegIndex >= NumInternalProcRegs) + fault = new UnimplementedOpcodeFault; + else + Ra = xc->readMiscRegWithEffect(miscRegIndex); }}, IsIprAccess); } } @@ -754,7 +760,13 @@ decode OPCODE default Unknown::unknown() { 0: OpcdecFault::hw_mtpr(); format HwMoveIPR { 1: hw_mtpr({{ - xc->setMiscRegWithEffect(ipr_index, Ra); + int miscRegIndex = (ipr_index < MaxInternalProcRegs) ? + IprToMiscRegIndex[ipr_index] : -1; + if(miscRegIndex < 0 || !IprIsWritable(miscRegIndex) || + miscRegIndex >= NumInternalProcRegs) + fault = new UnimplementedOpcodeFault; + else + xc->setMiscRegWithEffect(miscRegIndex, Ra); if (traceData) { traceData->setData(Ra); } }}, IsIprAccess); } @@ -783,12 +795,6 @@ decode OPCODE default Unknown::unknown() { 0x04: quiesceTime({{ R0 = AlphaPseudo::quiesceTime(xc->tcBase()); }}, IsNonSpeculative, IsUnverifiable); - 0x10: ivlb({{ - AlphaPseudo::ivlb(xc->tcBase()); - }}, No_OpClass, IsNonSpeculative); - 0x11: ivle({{ - AlphaPseudo::ivle(xc->tcBase()); - }}, No_OpClass, IsNonSpeculative); 0x20: m5exit_old({{ AlphaPseudo::m5exit_old(xc->tcBase()); }}, No_OpClass, IsNonSpeculative); diff --git a/src/arch/alpha/isa/fp.isa b/src/arch/alpha/isa/fp.isa index b4339a1b7..3b5575f62 100644 --- a/src/arch/alpha/isa/fp.isa +++ b/src/arch/alpha/isa/fp.isa @@ -46,7 +46,7 @@ output exec {{ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { Fault fault = NoFault; // dummy... this ipr access should not fault - if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR, fault))) { + if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR))) { fault = new FloatEnableFault; } return fault; @@ -229,7 +229,7 @@ def template FloatingPointExecute {{ %(code)s; } else { fesetround(getC99RoundingMode( - xc->readMiscReg(AlphaISA::Fpcr_DepTag))); + xc->readMiscReg(AlphaISA::MISCREG_FPCR))); %(code)s; fesetround(FE_TONEAREST); } diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index 2024b1117..6e65cf9d3 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -71,6 +71,7 @@ output exec {{ #if FULL_SYSTEM #include "sim/pseudo_inst.hh" #endif +#include "arch/alpha/ipr.hh" #include "base/fenv.hh" #include "config/ss_compatible_fp.hh" #include "cpu/base.hh" @@ -183,8 +184,9 @@ def operands {{ 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3), 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4), - 'Runiq': ('ControlReg', 'uq', 'TheISA::Uniq_DepTag', None, 1), - 'FPCR': (' ControlReg', 'uq', 'TheISA::Fpcr_DepTag', None, 1), + 'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1), + 'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1), + 'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', None, 1), # The next two are hacks for non-full-system call-pal emulation 'R0': ('IntReg', 'uq', '0', None, 1), 'R16': ('IntReg', 'uq', '16', None, 1), @@ -214,11 +216,6 @@ output header {{ /// live here and not in the AlphaISA namespace. enum DependenceTags { FP_Base_DepTag = AlphaISA::FP_Base_DepTag, - Fpcr_DepTag = AlphaISA::Fpcr_DepTag, - Uniq_DepTag = AlphaISA::Uniq_DepTag, - Lock_Flag_DepTag = AlphaISA::Lock_Flag_DepTag, - Lock_Addr_DepTag = AlphaISA::Lock_Addr_DepTag, - IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag }; /// Constructor. diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh index 4f439b8df..35d9ce843 100644 --- a/src/arch/alpha/isa_traits.hh +++ b/src/arch/alpha/isa_traits.hh @@ -34,6 +34,7 @@ namespace LittleEndianGuest {} +#include "arch/alpha/ipr.hh" #include "arch/alpha/types.hh" #include "config/full_system.hh" #include "sim/host.hh" @@ -49,12 +50,7 @@ namespace AlphaISA // 0..31 are the integer regs 0..31 // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) FP_Base_DepTag = 40, - Ctrl_Base_DepTag = 72, - Fpcr_DepTag = 72, // floating point control register - Uniq_DepTag = 73, - Lock_Flag_DepTag = 74, - Lock_Addr_DepTag = 75, - IPR_Base_DepTag = 76 + Ctrl_Base_DepTag = 72 }; StaticInstPtr decodeInst(ExtMachInst); @@ -118,7 +114,6 @@ namespace AlphaISA NumInterruptLevels = INTLEVEL_EXTERNAL_MAX }; - // EV5 modes enum mode_type { @@ -131,100 +126,6 @@ namespace AlphaISA #endif -#if FULL_SYSTEM - //////////////////////////////////////////////////////////////////////// - // - // Internal Processor Reigsters - // - enum md_ipr_names - { - IPR_ISR = 0x100, // interrupt summary register - IPR_ITB_TAG = 0x101, // ITLB tag register - IPR_ITB_PTE = 0x102, // ITLB page table entry register - IPR_ITB_ASN = 0x103, // ITLB address space register - IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register - IPR_ITB_IA = 0x105, // ITLB invalidate all register - IPR_ITB_IAP = 0x106, // ITLB invalidate all process register - IPR_ITB_IS = 0x107, // ITLB invalidate select register - IPR_SIRR = 0x108, // software interrupt request register - IPR_ASTRR = 0x109, // asynchronous system trap request register - IPR_ASTER = 0x10a, // asynchronous system trap enable register - IPR_EXC_ADDR = 0x10b, // exception address register - IPR_EXC_SUM = 0x10c, // exception summary register - IPR_EXC_MASK = 0x10d, // exception mask register - IPR_PAL_BASE = 0x10e, // PAL base address register - IPR_ICM = 0x10f, // instruction current mode - IPR_IPLR = 0x110, // interrupt priority level register - IPR_INTID = 0x111, // interrupt ID register - IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register - IPR_IVPTBR = 0x113, // virtual page table base register - IPR_HWINT_CLR = 0x115, // H/W interrupt clear register - IPR_SL_XMIT = 0x116, // serial line transmit register - IPR_SL_RCV = 0x117, // serial line receive register - IPR_ICSR = 0x118, // instruction control and status register - IPR_IC_FLUSH = 0x119, // instruction cache flush control - IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register - IPR_PMCTR = 0x11c, // performance counter register - - // PAL temporary registers... - // register meanings gleaned from osfpal.s source code - IPR_PALtemp0 = 0x140, // local scratch - IPR_PALtemp1 = 0x141, // local scratch - IPR_PALtemp2 = 0x142, // entUna - IPR_PALtemp3 = 0x143, // CPU specific impure area pointer - IPR_PALtemp4 = 0x144, // memory management temp - IPR_PALtemp5 = 0x145, // memory management temp - IPR_PALtemp6 = 0x146, // memory management temp - IPR_PALtemp7 = 0x147, // entIF - IPR_PALtemp8 = 0x148, // intmask - IPR_PALtemp9 = 0x149, // entSys - IPR_PALtemp10 = 0x14a, // ?? - IPR_PALtemp11 = 0x14b, // entInt - IPR_PALtemp12 = 0x14c, // entArith - IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL - IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL - IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL - IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0> - IPR_PALtemp17 = 0x151, // sysval - IPR_PALtemp18 = 0x152, // usp - IPR_PALtemp19 = 0x153, // ksp - IPR_PALtemp20 = 0x154, // PTBR - IPR_PALtemp21 = 0x155, // entMM - IPR_PALtemp22 = 0x156, // kgp - IPR_PALtemp23 = 0x157, // PCBB - - IPR_DTB_ASN = 0x200, // DTLB address space number register - IPR_DTB_CM = 0x201, // DTLB current mode register - IPR_DTB_TAG = 0x202, // DTLB tag register - IPR_DTB_PTE = 0x203, // DTLB page table entry register - IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register - - IPR_MM_STAT = 0x205, // data MMU fault status register - IPR_VA = 0x206, // fault virtual address register - IPR_VA_FORM = 0x207, // formatted virtual address register - IPR_MVPTBR = 0x208, // MTU virtual page table base register - IPR_DTB_IAP = 0x209, // DTLB invalidate all process register - IPR_DTB_IA = 0x20a, // DTLB invalidate all register - IPR_DTB_IS = 0x20b, // DTLB invalidate single register - IPR_ALT_MODE = 0x20c, // alternate mode register - IPR_CC = 0x20d, // cycle counter register - IPR_CC_CTL = 0x20e, // cycle counter control register - IPR_MCSR = 0x20f, // MTU control register - - IPR_DC_FLUSH = 0x210, - IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register - IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register - IPR_DC_TEST_TAG = 0x214, // Dcache test tag register - IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register - IPR_DC_MODE = 0x216, // Dcache mode register - IPR_MAF_MODE = 0x217, // miss address file mode register - - NumInternalProcRegs // number of IPR registers - }; -#else - const int NumInternalProcRegs = 0; -#endif - // Constants Related to the number of registers const int NumIntArchRegs = 32; @@ -279,9 +180,6 @@ namespace AlphaISA // Alpha UNOP (ldq_u r31,0(r0)) const ExtMachInst NoopMachInst = 0x2ffe0000; - // redirected register map, really only used for the full system case. - extern const int reg_redir[NumIntRegs]; - }; #endif // __ARCH_ALPHA_ISA_TRAITS_HH__ diff --git a/src/arch/alpha/kernel_stats.cc b/src/arch/alpha/kernel_stats.cc new file mode 100644 index 000000000..6fc3cb72f --- /dev/null +++ b/src/arch/alpha/kernel_stats.cc @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2004-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: Lisa Hsu + * Nathan Binkert + */ + +#include <map> +#include <stack> +#include <string> + +#include "arch/alpha/kernel_stats.hh" +#include "arch/alpha/osfpal.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "kern/tru64/tru64_syscalls.hh" +#include "sim/system.hh" + +using namespace std; +using namespace Stats; + +namespace AlphaISA { +namespace Kernel { + +const char *modestr[] = { "kernel", "user", "idle" }; + +Statistics::Statistics(System *system) + : ::Kernel::Statistics(system), + idleProcess((Addr)-1), themode(kernel), lastModeTick(0) +{ +} + +void +Statistics::regStats(const string &_name) +{ + ::Kernel::Statistics::regStats(_name); + + _callpal + .init(256) + .name(name() + ".callpal") + .desc("number of callpals executed") + .flags(total | pdf | nozero | nonan) + ; + + for (int i = 0; i < PAL::NumCodes; ++i) { + const char *str = PAL::name(i); + if (str) + _callpal.subname(i, str); + } + + _hwrei + .name(name() + ".inst.hwrei") + .desc("number of hwrei instructions executed") + ; + + _mode + .init(cpu_mode_num) + .name(name() + ".mode_switch") + .desc("number of protection mode switches") + ; + + for (int i = 0; i < cpu_mode_num; ++i) + _mode.subname(i, modestr[i]); + + _modeGood + .init(cpu_mode_num) + .name(name() + ".mode_good") + ; + + for (int i = 0; i < cpu_mode_num; ++i) + _modeGood.subname(i, modestr[i]); + + _modeFraction + .name(name() + ".mode_switch_good") + .desc("fraction of useful protection mode switches") + .flags(total) + ; + + for (int i = 0; i < cpu_mode_num; ++i) + _modeFraction.subname(i, modestr[i]); + + _modeFraction = _modeGood / _mode; + + _modeTicks + .init(cpu_mode_num) + .name(name() + ".mode_ticks") + .desc("number of ticks spent at the given mode") + .flags(pdf) + ; + for (int i = 0; i < cpu_mode_num; ++i) + _modeTicks.subname(i, modestr[i]); + + _swap_context + .name(name() + ".swap_context") + .desc("number of times the context was actually changed") + ; +} + +void +Statistics::setIdleProcess(Addr idlepcbb, ThreadContext *tc) +{ + assert(themode == kernel); + idleProcess = idlepcbb; + themode = idle; + changeMode(themode, tc); +} + +void +Statistics::changeMode(cpu_mode newmode, ThreadContext *tc) +{ + _mode[newmode]++; + + if (newmode == themode) + return; + + DPRINTF(Context, "old mode=%-8s new mode=%-8s\n", + modestr[themode], modestr[newmode]); + + _modeGood[newmode]++; + _modeTicks[themode] += curTick - lastModeTick; + + lastModeTick = curTick; + themode = newmode; +} + +void +Statistics::mode(cpu_mode newmode, ThreadContext *tc) +{ + Addr pcbb = tc->readMiscReg(AlphaISA::IPR_PALtemp23); + + if (newmode == kernel && pcbb == idleProcess) + newmode = idle; + + changeMode(newmode, tc); +} + +void +Statistics::context(Addr oldpcbb, Addr newpcbb, ThreadContext *tc) +{ + assert(themode != user); + + _swap_context++; + changeMode(newpcbb == idleProcess ? idle : kernel, tc); +} + +void +Statistics::callpal(int code, ThreadContext *tc) +{ + if (!PAL::name(code)) + return; + + _callpal[code]++; + + switch (code) { + case PAL::callsys: { + int number = tc->readIntReg(0); + if (SystemCalls<Tru64>::validSyscallNumber(number)) { + int cvtnum = SystemCalls<Tru64>::convert(number); + _syscall[cvtnum]++; + } + } break; + } +} + +void +Statistics::serialize(ostream &os) +{ + ::Kernel::Statistics::serialize(os); + int exemode = themode; + SERIALIZE_SCALAR(exemode); + SERIALIZE_SCALAR(idleProcess); + SERIALIZE_SCALAR(lastModeTick); +} + +void +Statistics::unserialize(Checkpoint *cp, const string §ion) +{ + ::Kernel::Statistics::unserialize(cp, section); + int exemode; + UNSERIALIZE_SCALAR(exemode); + UNSERIALIZE_SCALAR(idleProcess); + UNSERIALIZE_SCALAR(lastModeTick); + themode = (cpu_mode)exemode; +} + +} /* end namespace AlphaISA::Kernel */ +} /* end namespace AlphaISA */ diff --git a/src/arch/alpha/kernel_stats.hh b/src/arch/alpha/kernel_stats.hh new file mode 100644 index 000000000..7b8640ad7 --- /dev/null +++ b/src/arch/alpha/kernel_stats.hh @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004-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: Lisa Hsu + * Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_KERNEL_STATS_HH__ +#define __ARCH_ALPHA_KERNEL_STATS_HH__ + +#include <map> +#include <stack> +#include <string> +#include <vector> + +#include "cpu/static_inst.hh" +#include "kern/kernel_stats.hh" + +class BaseCPU; +class ThreadContext; +class FnEvent; +// What does kernel stats expect is included? +class System; + +namespace AlphaISA { +namespace Kernel { + +enum cpu_mode { kernel, user, idle, cpu_mode_num }; +extern const char *modestr[]; + +class Statistics : public ::Kernel::Statistics +{ + protected: + Addr idleProcess; + cpu_mode themode; + Tick lastModeTick; + + void changeMode(cpu_mode newmode, ThreadContext *tc); + + private: + Stats::Vector<> _callpal; +// Stats::Vector<> _faults; + + Stats::Vector<> _mode; + Stats::Vector<> _modeGood; + Stats::Formula _modeFraction; + Stats::Vector<> _modeTicks; + + Stats::Scalar<> _swap_context; + + public: + Statistics(System *system); + + void regStats(const std::string &name); + + public: + void mode(cpu_mode newmode, ThreadContext *tc); + void context(Addr oldpcbb, Addr newpcbb, ThreadContext *tc); + void callpal(int code, ThreadContext *tc); + void hwrei() { _hwrei++; } + + void setIdleProcess(Addr idle, ThreadContext *tc); + + public: + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); +}; + +} /* end namespace AlphaISA::Kernel */ +} /* end namespace AlphaISA */ + +#endif // __ARCH_ALPHA_KERNEL_STATS_HH__ diff --git a/src/arch/alpha/kgdb.h b/src/arch/alpha/kgdb.h new file mode 100644 index 000000000..912cf6d45 --- /dev/null +++ b/src/arch/alpha/kgdb.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)remote-sl.h 8.1 (Berkeley) 6/11/93 + */ + +/* $NetBSD: kgdb.h,v 1.4 1998/08/13 02:10:59 eeh Exp $ */ + +#ifndef __KGDB_H__ +#define __KGDB_H__ + +/* + * Message types. + */ +#define KGDB_SIGNAL '?' // last sigal +#define KGDB_SET_BAUD 'b' // set baud (deprecated) +#define KGDB_SET_BREAK 'B' // set breakpoint (deprecated) +#define KGDB_CONT 'c' // resume +#define KGDB_ASYNC_CONT 'C' // continue with signal +#define KGDB_DEBUG 'd' // toggle debug flags (deprecated) +#define KGDB_DETACH 'D' // detach remote gdb +#define KGDB_REG_R 'g' // read general registers +#define KGDB_REG_W 'G' // write general registers +#define KGDB_SET_THREAD 'H' // set thread +#define KGDB_CYCLE_STEP 'i' // step a single cycle +#define KGDB_SIG_CYCLE_STEP 'I' // signal then single cycle step +#define KGDB_KILL 'k' // kill program +#define KGDB_MEM_R 'm' // read memory +#define KGDB_MEM_W 'M' // write memory +#define KGDB_READ_REG 'p' // read register +#define KGDB_SET_REG 'P' // write register +#define KGDB_QUERY_VAR 'q' // query variable +#define KGDB_SET_VAR 'Q' // set variable +#define KGDB_RESET 'r' // reset system. (Deprecated) +#define KGDB_STEP 's' // step +#define KGDB_ASYNC_STEP 'S' // signal and step +#define KGDB_THREAD_ALIVE 'T' // find out if the thread is alive. +#define KGDB_TARGET_EXIT 'W' // target exited +#define KGDB_BINARY_DLOAD 'X' // write memory +#define KGDB_CLR_HW_BKPT 'z' // remove breakpoint or watchpoint +#define KGDB_SET_HW_BKPT 'Z' // insert breakpoint or watchpoint + +/* + * start of frame/end of frame + */ +#define KGDB_START '$' +#define KGDB_END '#' +#define KGDB_GOODP '+' +#define KGDB_BADP '-' + +/* + * Stuff for KGDB. + */ +#define KGDB_NUMREGS 66 /* from tm-alpha.h, NUM_REGS */ +#define KGDB_REG_V0 0 +#define KGDB_REG_T0 1 +#define KGDB_REG_T1 2 +#define KGDB_REG_T2 3 +#define KGDB_REG_T3 4 +#define KGDB_REG_T4 5 +#define KGDB_REG_T5 6 +#define KGDB_REG_T6 7 +#define KGDB_REG_T7 8 +#define KGDB_REG_S0 9 +#define KGDB_REG_S1 10 +#define KGDB_REG_S2 11 +#define KGDB_REG_S3 12 +#define KGDB_REG_S4 13 +#define KGDB_REG_S5 14 +#define KGDB_REG_S6 15 /* FP */ +#define KGDB_REG_A0 16 +#define KGDB_REG_A1 17 +#define KGDB_REG_A2 18 +#define KGDB_REG_A3 19 +#define KGDB_REG_A4 20 +#define KGDB_REG_A5 21 +#define KGDB_REG_T8 22 +#define KGDB_REG_T9 23 +#define KGDB_REG_T10 24 +#define KGDB_REG_T11 25 +#define KGDB_REG_RA 26 +#define KGDB_REG_T12 27 +#define KGDB_REG_AT 28 +#define KGDB_REG_GP 29 +#define KGDB_REG_SP 30 +#define KGDB_REG_ZERO 31 +#define KGDB_REG_F0 32 +#define KGDB_REG_F1 33 +#define KGDB_REG_F2 34 +#define KGDB_REG_F3 35 +#define KGDB_REG_F4 36 +#define KGDB_REG_F5 37 +#define KGDB_REG_F6 38 +#define KGDB_REG_F7 39 +#define KGDB_REG_F8 40 +#define KGDB_REG_F9 41 +#define KGDB_REG_F10 42 +#define KGDB_REG_F11 43 +#define KGDB_REG_F12 44 +#define KGDB_REG_F13 45 +#define KGDB_REG_F14 46 +#define KGDB_REG_F15 47 +#define KGDB_REG_F16 48 +#define KGDB_REG_F17 49 +#define KGDB_REG_F18 50 +#define KGDB_REG_F19 51 +#define KGDB_REG_F20 52 +#define KGDB_REG_F21 53 +#define KGDB_REG_F22 54 +#define KGDB_REG_F23 55 +#define KGDB_REG_F24 56 +#define KGDB_REG_F25 57 +#define KGDB_REG_F26 58 +#define KGDB_REG_F27 59 +#define KGDB_REG_F28 60 +#define KGDB_REG_F29 61 +#define KGDB_REG_F30 62 +#define KGDB_REG_F31 63 +#define KGDB_REG_PC 64 +#define KGDB_REG_VFP 65 + +/* Too much? Must be large enough for register transfer. */ +#define KGDB_BUFLEN 1024 + +#endif /* __KGDB_H__ */ diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc index 7cf234eeb..9a452e10f 100644 --- a/src/arch/alpha/linux/system.cc +++ b/src/arch/alpha/linux/system.cc @@ -42,6 +42,7 @@ #include "arch/arguments.hh" #include "arch/vtophys.hh" +#include "arch/alpha/idle_event.hh" #include "arch/alpha/linux/system.hh" #include "arch/alpha/linux/threadinfo.hh" #include "arch/alpha/system.hh" diff --git a/src/arch/alpha/linux/system.hh b/src/arch/alpha/linux/system.hh index 6921ba820..14396f8ab 100644 --- a/src/arch/alpha/linux/system.hh +++ b/src/arch/alpha/linux/system.hh @@ -38,6 +38,7 @@ class ThreadContext; class BreakPCEvent; class IdleStartEvent; +#include "arch/alpha/idle_event.hh" #include "arch/alpha/system.hh" #include "kern/linux/events.hh" diff --git a/src/arch/alpha/locked_mem.hh b/src/arch/alpha/locked_mem.hh index 368ea2895..52fe24173 100644 --- a/src/arch/alpha/locked_mem.hh +++ b/src/arch/alpha/locked_mem.hh @@ -37,7 +37,7 @@ * ISA-specific helper functions for locked memory accesses. */ -#include "arch/isa_traits.hh" +#include "arch/alpha/miscregfile.hh" #include "base/misc.hh" #include "mem/request.hh" @@ -48,8 +48,8 @@ template <class XC> inline void handleLockedRead(XC *xc, Request *req) { - xc->setMiscReg(Lock_Addr_DepTag, req->getPaddr() & ~0xf); - xc->setMiscReg(Lock_Flag_DepTag, true); + xc->setMiscReg(MISCREG_LOCKADDR, req->getPaddr() & ~0xf); + xc->setMiscReg(MISCREG_LOCKFLAG, true); } @@ -63,13 +63,13 @@ handleLockedWrite(XC *xc, Request *req) req->setScResult(2); } else { // standard store conditional - bool lock_flag = xc->readMiscReg(Lock_Flag_DepTag); - Addr lock_addr = xc->readMiscReg(Lock_Addr_DepTag); + bool lock_flag = xc->readMiscReg(MISCREG_LOCKFLAG); + Addr lock_addr = xc->readMiscReg(MISCREG_LOCKADDR); if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) { // Lock flag not set or addr mismatch in CPU; // don't even bother sending to memory system req->setScResult(0); - xc->setMiscReg(Lock_Flag_DepTag, false); + xc->setMiscReg(MISCREG_LOCKFLAG, false); // the rest of this code is not architectural; // it's just a debugging aid to help detect // livelock by warning on long sequences of failed diff --git a/src/arch/alpha/miscregfile.cc b/src/arch/alpha/miscregfile.cc new file mode 100644 index 000000000..4cf57a690 --- /dev/null +++ b/src/arch/alpha/miscregfile.cc @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2003-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: Steve Reinhardt + * Gabe Black + * Kevin Lim + */ + +#include "arch/alpha/miscregfile.hh" +#include "base/misc.hh" + +namespace AlphaISA +{ + + void + MiscRegFile::serialize(std::ostream &os) + { + SERIALIZE_SCALAR(fpcr); + SERIALIZE_SCALAR(uniq); + SERIALIZE_SCALAR(lock_flag); + SERIALIZE_SCALAR(lock_addr); +#if FULL_SYSTEM + SERIALIZE_ARRAY(ipr, NumInternalProcRegs); +#endif + } + + void + MiscRegFile::unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(fpcr); + UNSERIALIZE_SCALAR(uniq); + UNSERIALIZE_SCALAR(lock_flag); + UNSERIALIZE_SCALAR(lock_addr); +#if FULL_SYSTEM + UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs); +#endif + } + + MiscReg + MiscRegFile::readReg(int misc_reg) + { + switch(misc_reg) { + case MISCREG_FPCR: + return fpcr; + case MISCREG_UNIQ: + return uniq; + case MISCREG_LOCKFLAG: + return lock_flag; + case MISCREG_LOCKADDR: + 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 + } + } + + MiscReg + MiscRegFile::readRegWithEffect(int misc_reg, ThreadContext *tc) + { +#if FULL_SYSTEM + return readIpr(misc_reg, tc); +#else + panic("No faulting misc regs in SE mode!"); + return 0; +#endif + } + + void + MiscRegFile::setReg(int misc_reg, const MiscReg &val) + { + switch(misc_reg) { + case MISCREG_FPCR: + fpcr = val; + return; + case MISCREG_UNIQ: + uniq = val; + return; + case MISCREG_LOCKFLAG: + lock_flag = val; + return; + case MISCREG_LOCKADDR: + lock_addr = val; + return; + 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 + } + } + + void + MiscRegFile::setRegWithEffect(int misc_reg, const MiscReg &val, + ThreadContext *tc) + { +#if FULL_SYSTEM + switch(misc_reg) { + case MISCREG_FPCR: + fpcr = val; + return; + case MISCREG_UNIQ: + uniq = val; + return; + case MISCREG_LOCKFLAG: + lock_flag = val; + return; + case MISCREG_LOCKADDR: + lock_addr = val; + return; + case MISCREG_INTR: + intr_flag = val; + return; + default: + return setIpr(misc_reg, val, tc); + } +#else + //panic("No registers with side effects in SE mode!"); + return; +#endif + } + +} diff --git a/src/arch/alpha/miscregfile.hh b/src/arch/alpha/miscregfile.hh new file mode 100644 index 000000000..31b3e59b3 --- /dev/null +++ b/src/arch/alpha/miscregfile.hh @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2003-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: Steve Reinhardt + * Gabe Black + */ + +#ifndef __ARCH_ALPHA_MISCREGFILE_HH__ +#define __ARCH_ALPHA_MISCREGFILE_HH__ + +#include "arch/alpha/ipr.hh" +#include "arch/alpha/types.hh" +#include "config/full_system.hh" +#include "sim/host.hh" +#include "sim/serialize.hh" + +#include <iostream> + +class Checkpoint; +class ThreadContext; + +namespace AlphaISA +{ + enum MiscRegIndex + { + MISCREG_FPCR = NumInternalProcRegs, + MISCREG_UNIQ, + MISCREG_LOCKFLAG, + MISCREG_LOCKADDR, + MISCREG_INTR + }; + + static inline std::string getMiscRegName(RegIndex) + { + return ""; + } + + class MiscRegFile { + protected: + uint64_t fpcr; // floating point condition codes + uint64_t uniq; // process-unique register + bool lock_flag; // lock flag for LL/SC + Addr lock_addr; // lock address for LL/SC + int intr_flag; + + public: + MiscRegFile() + { +#if FULL_SYSTEM + initializeIprTable(); +#endif + } + + MiscReg readReg(int misc_reg); + + MiscReg readRegWithEffect(int misc_reg, ThreadContext *tc); + + //These functions should be removed once the simplescalar cpu model + //has been replaced. + int getInstAsid(); + int getDataAsid(); + + void setReg(int misc_reg, const MiscReg &val); + + void setRegWithEffect(int misc_reg, const MiscReg &val, + ThreadContext *tc); + + void clear() + { + fpcr = uniq = 0; + lock_flag = 0; + lock_addr = 0; + intr_flag = 0; + } + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); +#if FULL_SYSTEM + protected: + typedef uint64_t InternalProcReg; + + InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs + + private: + 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 + +} + +#endif diff --git a/src/arch/alpha/pagetable.cc b/src/arch/alpha/pagetable.cc new file mode 100644 index 000000000..0c26ccbe3 --- /dev/null +++ b/src/arch/alpha/pagetable.cc @@ -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 + */ + +#include "arch/alpha/pagetable.hh" +#include "sim/serialize.hh" + +namespace AlphaISA +{ + void + PTE::serialize(std::ostream &os) + { + SERIALIZE_SCALAR(tag); + SERIALIZE_SCALAR(ppn); + SERIALIZE_SCALAR(xre); + SERIALIZE_SCALAR(xwe); + SERIALIZE_SCALAR(asn); + SERIALIZE_SCALAR(asma); + SERIALIZE_SCALAR(fonr); + SERIALIZE_SCALAR(fonw); + SERIALIZE_SCALAR(valid); + } + + void + PTE::unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(tag); + UNSERIALIZE_SCALAR(ppn); + UNSERIALIZE_SCALAR(xre); + UNSERIALIZE_SCALAR(xwe); + UNSERIALIZE_SCALAR(asn); + UNSERIALIZE_SCALAR(asma); + UNSERIALIZE_SCALAR(fonr); + UNSERIALIZE_SCALAR(fonw); + UNSERIALIZE_SCALAR(valid); + } +} diff --git a/src/arch/alpha/regfile.cc b/src/arch/alpha/regfile.cc new file mode 100644 index 000000000..92e1b07df --- /dev/null +++ b/src/arch/alpha/regfile.cc @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2003-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: Steve Reinhardt + * Gabe Black + * Kevin Lim + */ + +#include "arch/alpha/regfile.hh" +#include "cpu/thread_context.hh" + +namespace AlphaISA +{ + void + RegFile::serialize(std::ostream &os) + { + intRegFile.serialize(os); + floatRegFile.serialize(os); + miscRegFile.serialize(os); + SERIALIZE_SCALAR(pc); + SERIALIZE_SCALAR(npc); +#if FULL_SYSTEM + SERIALIZE_SCALAR(intrflag); +#endif + } + + void + RegFile::unserialize(Checkpoint *cp, const std::string §ion) + { + intRegFile.unserialize(cp, section); + floatRegFile.unserialize(cp, section); + miscRegFile.unserialize(cp, section); + UNSERIALIZE_SCALAR(pc); + UNSERIALIZE_SCALAR(npc); +#if FULL_SYSTEM + UNSERIALIZE_SCALAR(intrflag); +#endif + } + + void + copyRegs(ThreadContext *src, ThreadContext *dest) + { + // First loop through the integer registers. + for (int i = 0; i < NumIntRegs; ++i) { + dest->setIntReg(i, src->readIntReg(i)); + } + + // Then loop through the floating point registers. + for (int i = 0; i < TheISA::NumFloatRegs; ++i) { + dest->setFloatRegBits(i, src->readFloatRegBits(i)); + } + + // Copy misc. registers + copyMiscRegs(src, dest); + + // Lastly copy PC/NPC + dest->setPC(src->readPC()); + dest->setNextPC(src->readNextPC()); + } + + void + copyMiscRegs(ThreadContext *src, ThreadContext *dest) + { + dest->setMiscReg(AlphaISA::MISCREG_FPCR, + src->readMiscReg(AlphaISA::MISCREG_FPCR)); + dest->setMiscReg(AlphaISA::MISCREG_UNIQ, + src->readMiscReg(AlphaISA::MISCREG_UNIQ)); + dest->setMiscReg(AlphaISA::MISCREG_LOCKFLAG, + src->readMiscReg(AlphaISA::MISCREG_LOCKFLAG)); + dest->setMiscReg(AlphaISA::MISCREG_LOCKADDR, + src->readMiscReg(AlphaISA::MISCREG_LOCKADDR)); + +#if FULL_SYSTEM + copyIprs(src, dest); +#endif + } +} diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index 43b48a0ab..ff5830822 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -31,8 +31,11 @@ #ifndef __ARCH_ALPHA_REGFILE_HH__ #define __ARCH_ALPHA_REGFILE_HH__ -#include "arch/alpha/types.hh" #include "arch/alpha/isa_traits.hh" +#include "arch/alpha/floatregfile.hh" +#include "arch/alpha/intregfile.hh" +#include "arch/alpha/miscregfile.hh" +#include "arch/alpha/types.hh" #include "sim/faults.hh" #include <string> @@ -45,111 +48,6 @@ class ThreadContext; namespace AlphaISA { - static inline std::string getIntRegName(RegIndex) - { - return ""; - } - - static inline std::string getFloatRegName(RegIndex) - { - return ""; - } - - static inline std::string getMiscRegName(RegIndex) - { - return ""; - } - - class IntRegFile - { - protected: - IntReg regs[NumIntRegs]; - - public: - - IntReg readReg(int intReg) - { - return regs[intReg]; - } - - Fault setReg(int intReg, const IntReg &val) - { - regs[intReg] = val; - return NoFault; - } - - void serialize(std::ostream &os); - - void unserialize(Checkpoint *cp, const std::string §ion); - - void clear() - { bzero(regs, sizeof(regs)); } - }; - - class FloatRegFile - { - public: - - union { - uint64_t q[NumFloatRegs]; // integer qword view - double d[NumFloatRegs]; // double-precision floating point view - }; - - void serialize(std::ostream &os); - - void unserialize(Checkpoint *cp, const std::string §ion); - - void clear() - { bzero(d, sizeof(d)); } - }; - - class MiscRegFile { - protected: - uint64_t fpcr; // floating point condition codes - uint64_t uniq; // process-unique register - bool lock_flag; // lock flag for LL/SC - Addr lock_addr; // lock address for LL/SC - - public: - MiscReg readReg(int misc_reg); - - MiscReg readRegWithEffect(int misc_reg, Fault &fault, - ThreadContext *tc); - - //These functions should be removed once the simplescalar cpu model - //has been replaced. - int getInstAsid(); - int getDataAsid(); - - Fault setReg(int misc_reg, const MiscReg &val); - - Fault setRegWithEffect(int misc_reg, const MiscReg &val, - ThreadContext *tc); - - void clear() - { - fpcr = uniq = 0; - lock_flag = 0; - lock_addr = 0; - } - - void serialize(std::ostream &os); - - void unserialize(Checkpoint *cp, const std::string §ion); -#if FULL_SYSTEM - protected: - typedef uint64_t InternalProcReg; - - InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs - - private: - InternalProcReg readIpr(int idx, Fault &fault, ThreadContext *tc); - - Fault setIpr(int idx, InternalProcReg val, ThreadContext *tc); -#endif - friend class RegFile; - }; - class RegFile { protected: @@ -215,22 +113,20 @@ namespace AlphaISA return miscRegFile.readReg(miscReg); } - MiscReg readMiscRegWithEffect(int miscReg, - Fault &fault, ThreadContext *tc) + MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc) { - fault = NoFault; - return miscRegFile.readRegWithEffect(miscReg, fault, tc); + return miscRegFile.readRegWithEffect(miscReg, tc); } - Fault setMiscReg(int miscReg, const MiscReg &val) + void setMiscReg(int miscReg, const MiscReg &val) { - return miscRegFile.setReg(miscReg, val); + miscRegFile.setReg(miscReg, val); } - Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, + void setMiscRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc) { - return miscRegFile.setRegWithEffect(miscReg, val, tc); + miscRegFile.setRegWithEffect(miscReg, val, tc); } FloatReg readFloatReg(int floatReg) @@ -253,26 +149,24 @@ namespace AlphaISA return readFloatRegBits(floatReg); } - Fault setFloatReg(int floatReg, const FloatReg &val) + void setFloatReg(int floatReg, const FloatReg &val) { floatRegFile.d[floatReg] = val; - return NoFault; } - Fault setFloatReg(int floatReg, const FloatReg &val, int width) + void setFloatReg(int floatReg, const FloatReg &val, int width) { - return setFloatReg(floatReg, val); + setFloatReg(floatReg, val); } - Fault setFloatRegBits(int floatReg, const FloatRegBits &val) + void setFloatRegBits(int floatReg, const FloatRegBits &val) { floatRegFile.q[floatReg] = val; - return NoFault; } - Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width) + void setFloatRegBits(int floatReg, const FloatRegBits &val, int width) { - return setFloatRegBits(floatReg, val); + setFloatRegBits(floatReg, val); } IntReg readIntReg(int intReg) @@ -280,9 +174,9 @@ namespace AlphaISA return intRegFile.readReg(intReg); } - Fault setIntReg(int intReg, const IntReg &val) + void setIntReg(int intReg, const IntReg &val) { - return intRegFile.setReg(intReg, val); + intRegFile.setReg(intReg, val); } void serialize(std::ostream &os); @@ -298,10 +192,6 @@ namespace AlphaISA void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); - -#if FULL_SYSTEM - void copyIprs(ThreadContext *src, ThreadContext *dest); -#endif } // namespace AlphaISA #endif diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc new file mode 100644 index 000000000..f23fc3205 --- /dev/null +++ b/src/arch/alpha/remote_gdb.cc @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2002-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: Nathan Binkert + */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 + */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ + * + * Taken from NetBSD + * + * "Stub" to allow remote cpu to debug over a serial line using gdb. + */ + +#include <sys/signal.h> + +#include <string> +#include <unistd.h> + +#include "arch/alpha/kgdb.h" +#include "arch/alpha/remote_gdb.hh" +#include "arch/vtophys.hh" +#include "base/intmath.hh" +#include "base/remote_gdb.hh" +#include "base/socket.hh" +#include "base/trace.hh" +#include "config/full_system.hh" +#include "cpu/thread_context.hh" +#include "cpu/static_inst.hh" +#include "mem/physical.hh" +#include "mem/port.hh" +#include "sim/system.hh" + +using namespace std; +using namespace TheISA; + +RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) + : BaseRemoteGDB(_system, c, KGDB_NUMREGS) +{ + memset(gdbregs.regs, 0, gdbregs.bytes()); +} + +/////////////////////////////////////////////////////////// +// RemoteGDB::acc +// +// Determine if the mapping at va..(va+len) is valid. +// +bool +RemoteGDB::acc(Addr va, size_t len) +{ + Addr last_va; + + va = TheISA::TruncPage(va); + last_va = TheISA::RoundPage(va + len); + + do { + if (TheISA::IsK0Seg(va)) { + if (va < (TheISA::K0SegBase + pmem->size())) { + DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= " + "%#x < K0SEG + size\n", va); + return true; + } else { + DPRINTF(GDBAcc, "acc: Mapping invalid %#x > K0SEG + size\n", + va); + return false; + } + } + + /** + * This code says that all accesses to palcode (instruction and data) + * are valid since there isn't a va->pa mapping because palcode is + * accessed physically. At some point this should probably be cleaned up + * but there is no easy way to do it. + */ + + if (AlphaISA::PcPAL(va) || va < 0x10000) + return true; + + Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20); + TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va); + if (!pte.valid()) { + DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); + return false; + } + va += TheISA::PageBytes; + } while (va < last_va); + + DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va); + return true; +} + +/////////////////////////////////////////////////////////// +// RemoteGDB::getregs +// +// Translate the kernel debugger register format into +// the GDB register format. +void +RemoteGDB::getregs() +{ + memset(gdbregs.regs, 0, gdbregs.bytes()); + + gdbregs.regs[KGDB_REG_PC] = context->readPC(); + + // @todo: Currently this is very Alpha specific. + if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) { + for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { + gdbregs.regs[i] = context->readIntReg(AlphaISA::reg_redir[i]); + } + } else { + for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { + gdbregs.regs[i] = context->readIntReg(i); + } + } + +#ifdef KGDB_FP_REGS + for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { + gdbregs.regs[i + KGDB_REG_F0] = context->readFloatRegBits(i); + } +#endif +} + +/////////////////////////////////////////////////////////// +// RemoteGDB::setregs +// +// Translate the GDB register format into the kernel +// debugger register format. +// +void +RemoteGDB::setregs() +{ + // @todo: Currently this is very Alpha specific. + if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) { + for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { + context->setIntReg(AlphaISA::reg_redir[i], gdbregs.regs[i]); + } + } else { + for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { + context->setIntReg(i, gdbregs.regs[i]); + } + } + +#ifdef KGDB_FP_REGS + for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { + context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]); + } +#endif + context->setPC(gdbregs.regs[KGDB_REG_PC]); +} + +void +RemoteGDB::clearSingleStep() +{ + DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n", + takenBkpt, notTakenBkpt); + + if (takenBkpt != 0) + clearTempBreakpoint(takenBkpt); + + if (notTakenBkpt != 0) + clearTempBreakpoint(notTakenBkpt); +} + +void +RemoteGDB::setSingleStep() +{ + Addr pc = context->readPC(); + Addr npc, bpc; + bool set_bt = false; + + npc = pc + sizeof(MachInst); + + // User was stopped at pc, e.g. the instruction at pc was not + // executed. + MachInst inst = read<MachInst>(pc); + StaticInstPtr si(inst); + if (si->hasBranchTarget(pc, context, bpc)) { + // Don't bother setting a breakpoint on the taken branch if it + // is the same as the next pc + if (bpc != npc) + set_bt = true; + } + + DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n", + takenBkpt, notTakenBkpt); + + setTempBreakpoint(notTakenBkpt = npc); + + if (set_bt) + setTempBreakpoint(takenBkpt = bpc); +} + +// Write bytes to kernel address space for debugger. +bool +RemoteGDB::write(Addr vaddr, size_t size, const char *data) +{ + if (BaseRemoteGDB::write(vaddr, size, data)) { +#ifdef IMB + alpha_pal_imb(); +#endif + return true; + } else { + return false; + } +} + diff --git a/src/arch/alpha/remote_gdb.hh b/src/arch/alpha/remote_gdb.hh new file mode 100644 index 000000000..7bef183c3 --- /dev/null +++ b/src/arch/alpha/remote_gdb.hh @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2002-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: Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_REMOTE_GDB_HH__ +#define __ARCH_ALPHA_REMOTE_GDB_HH__ + +#include <map> + +#include "arch/alpha/types.hh" +#include "arch/alpha/kgdb.h" +#include "base/remote_gdb.hh" +#include "cpu/pc_event.hh" +#include "base/pollevent.hh" +#include "base/socket.hh" + +class System; +class ThreadContext; +class PhysicalMemory; + +namespace AlphaISA +{ + class RemoteGDB : public BaseRemoteGDB + { + protected: + // Machine memory + bool write(Addr addr, size_t size, const char *data); + + public: + RemoteGDB(System *system, ThreadContext *context); + + bool acc(Addr addr, size_t len); + + protected: + void getregs(); + void setregs(); + + void clearSingleStep(); + void setSingleStep(); + + protected: + + Addr notTakenBkpt; + Addr takenBkpt; + }; +} + +#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */ diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc index d70a4d6dd..c4612e156 100644 --- a/src/arch/alpha/stacktrace.cc +++ b/src/arch/alpha/stacktrace.cc @@ -40,329 +40,331 @@ #include "sim/system.hh" using namespace std; -using namespace AlphaISA; -ProcessInfo::ProcessInfo(ThreadContext *_tc) - : tc(_tc) +namespace AlphaISA { - Addr addr = 0; + ProcessInfo::ProcessInfo(ThreadContext *_tc) + : tc(_tc) + { + Addr addr = 0; - VirtualPort *vp; + VirtualPort *vp; - vp = tc->getVirtPort(); + vp = tc->getVirtPort(); - if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) - panic("thread info not compiled into kernel\n"); - thread_info_size = vp->readGtoH<int32_t>(addr); + if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) + panic("thread info not compiled into kernel\n"); + thread_info_size = vp->readGtoH<int32_t>(addr); - if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) - panic("thread info not compiled into kernel\n"); - task_struct_size = vp->readGtoH<int32_t>(addr); + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) + panic("thread info not compiled into kernel\n"); + task_struct_size = vp->readGtoH<int32_t>(addr); - if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) - panic("thread info not compiled into kernel\n"); - task_off = vp->readGtoH<int32_t>(addr); + if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) + panic("thread info not compiled into kernel\n"); + task_off = vp->readGtoH<int32_t>(addr); - if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) - panic("thread info not compiled into kernel\n"); - pid_off = vp->readGtoH<int32_t>(addr); + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) + panic("thread info not compiled into kernel\n"); + pid_off = vp->readGtoH<int32_t>(addr); - if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) - panic("thread info not compiled into kernel\n"); - name_off = vp->readGtoH<int32_t>(addr); + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) + panic("thread info not compiled into kernel\n"); + name_off = vp->readGtoH<int32_t>(addr); - tc->delVirtPort(vp); -} - -Addr -ProcessInfo::task(Addr ksp) const -{ - Addr base = ksp & ~0x3fff; - if (base == ULL(0xfffffc0000000000)) - return 0; + tc->delVirtPort(vp); + } - Addr tsk; + Addr + ProcessInfo::task(Addr ksp) const + { + Addr base = ksp & ~0x3fff; + if (base == ULL(0xfffffc0000000000)) + return 0; - VirtualPort *vp; + Addr tsk; - vp = tc->getVirtPort(); - tsk = vp->readGtoH<Addr>(base + task_off); - tc->delVirtPort(vp); + VirtualPort *vp; - return tsk; -} + vp = tc->getVirtPort(); + tsk = vp->readGtoH<Addr>(base + task_off); + tc->delVirtPort(vp); -int -ProcessInfo::pid(Addr ksp) const -{ - Addr task = this->task(ksp); - if (!task) - return -1; + return tsk; + } - uint16_t pd; + int + ProcessInfo::pid(Addr ksp) const + { + Addr task = this->task(ksp); + if (!task) + return -1; - VirtualPort *vp; + uint16_t pd; - vp = tc->getVirtPort(); - pd = vp->readGtoH<uint16_t>(task + pid_off); - tc->delVirtPort(vp); + VirtualPort *vp; - return pd; -} + vp = tc->getVirtPort(); + pd = vp->readGtoH<uint16_t>(task + pid_off); + tc->delVirtPort(vp); -string -ProcessInfo::name(Addr ksp) const -{ - Addr task = this->task(ksp); - if (!task) - return "console"; + return pd; + } - char comm[256]; - CopyStringOut(tc, comm, task + name_off, sizeof(comm)); - if (!comm[0]) - return "startup"; + string + ProcessInfo::name(Addr ksp) const + { + Addr task = this->task(ksp); + if (!task) + return "console"; - return comm; -} + char comm[256]; + CopyStringOut(tc, comm, task + name_off, sizeof(comm)); + if (!comm[0]) + return "startup"; -StackTrace::StackTrace() - : tc(0), stack(64) -{ -} + return comm; + } -StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) - : tc(0), stack(64) -{ - trace(_tc, inst); -} + StackTrace::StackTrace() + : tc(0), stack(64) + { + } -StackTrace::~StackTrace() -{ -} + StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) + : tc(0), stack(64) + { + trace(_tc, inst); + } -void -StackTrace::trace(ThreadContext *_tc, bool is_call) -{ - tc = _tc; + StackTrace::~StackTrace() + { + } - bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + void + StackTrace::trace(ThreadContext *_tc, bool is_call) + { + tc = _tc; - Addr pc = tc->readNextPC(); - bool kernel = tc->getSystemPtr()->kernelStart <= pc && - pc <= tc->getSystemPtr()->kernelEnd; + bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; - if (usermode) { - stack.push_back(user); - return; - } + Addr pc = tc->readNextPC(); + bool kernel = tc->getSystemPtr()->kernelStart <= pc && + pc <= tc->getSystemPtr()->kernelEnd; - if (!kernel) { - stack.push_back(console); - return; - } + if (usermode) { + stack.push_back(user); + return; + } - SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; - Addr ksp = tc->readIntReg(TheISA::StackPointerReg); - Addr bottom = ksp & ~0x3fff; - Addr addr; + if (!kernel) { + stack.push_back(console); + return; + } - if (is_call) { - if (!symtab->findNearestAddr(pc, addr)) - panic("could not find address %#x", pc); + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; + Addr ksp = tc->readIntReg(TheISA::StackPointerReg); + Addr bottom = ksp & ~0x3fff; + Addr addr; - stack.push_back(addr); - pc = tc->readPC(); - } + if (is_call) { + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find address %#x", pc); - Addr ra; - int size; + stack.push_back(addr); + pc = tc->readPC(); + } - while (ksp > bottom) { - if (!symtab->findNearestAddr(pc, addr)) - panic("could not find symbol for pc=%#x", pc); - assert(pc >= addr && "symbol botch: callpc < func"); + Addr ra; + int size; - stack.push_back(addr); + while (ksp > bottom) { + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find symbol for pc=%#x", pc); + assert(pc >= addr && "symbol botch: callpc < func"); - if (isEntry(addr)) - return; + stack.push_back(addr); - if (decodePrologue(ksp, pc, addr, size, ra)) { - if (!ra) + if (isEntry(addr)) return; - if (size <= 0) { + if (decodePrologue(ksp, pc, addr, size, ra)) { + if (!ra) + return; + + if (size <= 0) { + stack.push_back(unknown); + return; + } + + pc = ra; + ksp += size; + } else { stack.push_back(unknown); return; } - pc = ra; - ksp += size; - } else { - stack.push_back(unknown); - return; - } + bool kernel = tc->getSystemPtr()->kernelStart <= pc && + pc <= tc->getSystemPtr()->kernelEnd; + if (!kernel) + return; - bool kernel = tc->getSystemPtr()->kernelStart <= pc && - pc <= tc->getSystemPtr()->kernelEnd; - if (!kernel) - return; + if (stack.size() >= 1000) + panic("unwinding too far"); + } - if (stack.size() >= 1000) - panic("unwinding too far"); + panic("unwinding too far"); } - panic("unwinding too far"); -} + bool + StackTrace::isEntry(Addr addr) + { + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12)) + return true; -bool -StackTrace::isEntry(Addr addr) -{ - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12)) - return true; + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7)) + return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7)) - return true; + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11)) + return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11)) - return true; + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21)) + return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21)) - return true; + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9)) + return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9)) - return true; - - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2)) - return true; + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2)) + return true; - return false; -} - -bool -StackTrace::decodeStack(MachInst inst, int &disp) -{ - // lda $sp, -disp($sp) - // - // Opcode<31:26> == 0x08 - // RA<25:21> == 30 - // RB<20:16> == 30 - // Disp<15:0> - const MachInst mem_mask = 0xffff0000; - const MachInst lda_pattern = 0x23de0000; - const MachInst lda_disp_mask = 0x0000ffff; - - // subq $sp, disp, $sp - // addq $sp, disp, $sp - // - // Opcode<31:26> == 0x10 - // RA<25:21> == 30 - // Lit<20:13> - // One<12> = 1 - // Func<11:5> == 0x20 (addq) - // Func<11:5> == 0x29 (subq) - // RC<4:0> == 30 - const MachInst intop_mask = 0xffe01fff; - const MachInst addq_pattern = 0x43c0141e; - const MachInst subq_pattern = 0x43c0153e; - const MachInst intop_disp_mask = 0x001fe000; - const int intop_disp_shift = 13; - - if ((inst & mem_mask) == lda_pattern) - disp = -sext<16>(inst & lda_disp_mask); - else if ((inst & intop_mask) == addq_pattern) - disp = -int((inst & intop_disp_mask) >> intop_disp_shift); - else if ((inst & intop_mask) == subq_pattern) - disp = int((inst & intop_disp_mask) >> intop_disp_shift); - else return false; + } - return true; -} + bool + StackTrace::decodeStack(MachInst inst, int &disp) + { + // lda $sp, -disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == 30 + // RB<20:16> == 30 + // Disp<15:0> + const MachInst mem_mask = 0xffff0000; + const MachInst lda_pattern = 0x23de0000; + const MachInst lda_disp_mask = 0x0000ffff; + + // subq $sp, disp, $sp + // addq $sp, disp, $sp + // + // Opcode<31:26> == 0x10 + // RA<25:21> == 30 + // Lit<20:13> + // One<12> = 1 + // Func<11:5> == 0x20 (addq) + // Func<11:5> == 0x29 (subq) + // RC<4:0> == 30 + const MachInst intop_mask = 0xffe01fff; + const MachInst addq_pattern = 0x43c0141e; + const MachInst subq_pattern = 0x43c0153e; + const MachInst intop_disp_mask = 0x001fe000; + const int intop_disp_shift = 13; + + if ((inst & mem_mask) == lda_pattern) + disp = -sext<16>(inst & lda_disp_mask); + else if ((inst & intop_mask) == addq_pattern) + disp = -int((inst & intop_disp_mask) >> intop_disp_shift); + else if ((inst & intop_mask) == subq_pattern) + disp = int((inst & intop_disp_mask) >> intop_disp_shift); + else + return false; -bool -StackTrace::decodeSave(MachInst inst, int ®, int &disp) -{ - // lda $stq, disp($sp) - // - // Opcode<31:26> == 0x08 - // RA<25:21> == ? - // RB<20:16> == 30 - // Disp<15:0> - const MachInst stq_mask = 0xfc1f0000; - const MachInst stq_pattern = 0xb41e0000; - const MachInst stq_disp_mask = 0x0000ffff; - const MachInst reg_mask = 0x03e00000; - const int reg_shift = 21; - - if ((inst & stq_mask) == stq_pattern) { - reg = (inst & reg_mask) >> reg_shift; - disp = sext<16>(inst & stq_disp_mask); - } else { - return false; + return true; } - return true; -} + bool + StackTrace::decodeSave(MachInst inst, int ®, int &disp) + { + // lda $stq, disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == ? + // RB<20:16> == 30 + // Disp<15:0> + const MachInst stq_mask = 0xfc1f0000; + const MachInst stq_pattern = 0xb41e0000; + const MachInst stq_disp_mask = 0x0000ffff; + const MachInst reg_mask = 0x03e00000; + const int reg_shift = 21; + + if ((inst & stq_mask) == stq_pattern) { + reg = (inst & reg_mask) >> reg_shift; + disp = sext<16>(inst & stq_disp_mask); + } else { + return false; + } -/* - * Decode the function prologue for the function we're in, and note - * which registers are stored where, and how large the stack frame is. - */ -bool -StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, - int &size, Addr &ra) -{ - size = 0; - ra = 0; - - for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { - MachInst inst; - CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); - - int reg, disp; - if (decodeStack(inst, disp)) { - if (size) { - // panic("decoding frame size again"); - return true; - } - size += disp; - } else if (decodeSave(inst, reg, disp)) { - if (!ra && reg == ReturnAddressReg) { - CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); - if (!ra) { - // panic("no return address value pc=%#x\n", pc); - return false; + return true; + } + + /* + * Decode the function prologue for the function we're in, and note + * which registers are stored where, and how large the stack frame is. + */ + bool + StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, + int &size, Addr &ra) + { + size = 0; + ra = 0; + + for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { + MachInst inst; + CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); + + int reg, disp; + if (decodeStack(inst, disp)) { + if (size) { + // panic("decoding frame size again"); + return true; + } + size += disp; + } else if (decodeSave(inst, reg, disp)) { + if (!ra && reg == ReturnAddressReg) { + CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); + if (!ra) { + // panic("no return address value pc=%#x\n", pc); + return false; + } } } } - } - return true; -} + return true; + } #if TRACING_ON -void -StackTrace::dump() -{ - StringWrap name(tc->getCpuPtr()->name()); - SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; - - DPRINTFN("------ Stack ------\n"); - - string symbol; - for (int i = 0, size = stack.size(); i < size; ++i) { - Addr addr = stack[size - i - 1]; - if (addr == user) - symbol = "user"; - else if (addr == console) - symbol = "console"; - else if (addr == unknown) - symbol = "unknown"; - else - symtab->findSymbol(addr, symbol); - - DPRINTFN("%#x: %s\n", addr, symbol); + void + StackTrace::dump() + { + StringWrap name(tc->getCpuPtr()->name()); + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; + + DPRINTFN("------ Stack ------\n"); + + string symbol; + for (int i = 0, size = stack.size(); i < size; ++i) { + Addr addr = stack[size - i - 1]; + if (addr == user) + symbol = "user"; + else if (addr == console) + symbol = "console"; + else if (addr == unknown) + symbol = "unknown"; + else + symtab->findSymbol(addr, symbol); + + DPRINTFN("%#x: %s\n", addr, symbol); + } } -} #endif +} diff --git a/src/arch/alpha/stacktrace.hh b/src/arch/alpha/stacktrace.hh index d12aee211..834abbc2f 100644 --- a/src/arch/alpha/stacktrace.hh +++ b/src/arch/alpha/stacktrace.hh @@ -35,87 +35,91 @@ #include "cpu/static_inst.hh" class ThreadContext; -class StackTrace; -class ProcessInfo +namespace AlphaISA { - private: - ThreadContext *tc; + class StackTrace; - int thread_info_size; - int task_struct_size; - int task_off; - int pid_off; - int name_off; + class ProcessInfo + { + private: + ThreadContext *tc; - public: - ProcessInfo(ThreadContext *_tc); + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; - Addr task(Addr ksp) const; - int pid(Addr ksp) const; - std::string name(Addr ksp) const; -}; + public: + ProcessInfo(ThreadContext *_tc); -class StackTrace -{ - protected: - typedef TheISA::MachInst MachInst; - private: - ThreadContext *tc; - std::vector<Addr> stack; - - private: - bool isEntry(Addr addr); - bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); - bool decodeSave(MachInst inst, int ®, int &disp); - bool decodeStack(MachInst inst, int &disp); - - void trace(ThreadContext *tc, bool is_call); - - public: - StackTrace(); - StackTrace(ThreadContext *tc, StaticInstPtr inst); - ~StackTrace(); - - void clear() + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; + }; + + class StackTrace { - tc = 0; - stack.clear(); - } + protected: + typedef TheISA::MachInst MachInst; + private: + ThreadContext *tc; + std::vector<Addr> stack; + + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); + + void trace(ThreadContext *tc, bool is_call); - bool valid() const { return tc != NULL; } - bool trace(ThreadContext *tc, StaticInstPtr inst); + public: + StackTrace(); + StackTrace(ThreadContext *tc, StaticInstPtr inst); + ~StackTrace(); - public: - const std::vector<Addr> &getstack() const { return stack; } + void clear() + { + tc = 0; + stack.clear(); + } - static const int user = 1; - static const int console = 2; - static const int unknown = 3; + bool valid() const { return tc != NULL; } + bool trace(ThreadContext *tc, StaticInstPtr inst); + + public: + const std::vector<Addr> &getstack() const { return stack; } + + static const int user = 1; + static const int console = 2; + static const int unknown = 3; #if TRACING_ON - private: - void dump(); + private: + void dump(); - public: - void dprintf() { if (DTRACE(Stack)) dump(); } + public: + void dprintf() { if (DTRACE(Stack)) dump(); } #else - public: - void dprintf() {} + public: + void dprintf() {} #endif -}; + }; -inline bool -StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) -{ - if (!inst->isCall() && !inst->isReturn()) - return false; + inline bool + StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) + { + if (!inst->isCall() && !inst->isReturn()) + return false; - if (valid()) - clear(); + if (valid()) + clear(); - trace(tc, !inst->isReturn()); - return true; + trace(tc, !inst->isReturn()); + return true; + } } #endif // __ARCH_ALPHA_STACKTRACE_HH__ diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index 5597eaedc..cd923948c 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -29,10 +29,12 @@ * Nathan Binkert */ +#include <sys/signal.h> + #include "arch/alpha/ev5.hh" #include "arch/alpha/system.hh" +#include "arch/alpha/remote_gdb.hh" #include "arch/vtophys.hh" -#include "base/remote_gdb.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" @@ -196,7 +198,7 @@ AlphaSystem::setAlphaAccess(Addr access) bool AlphaSystem::breakpoint() { - return remoteGDB[0]->trap(ALPHA_KENTRY_INT); + return remoteGDB[0]->trap(SIGTRAP); } void diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index bab44c434..ae302e686 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -46,589 +46,591 @@ using namespace std; using namespace EV5; -/////////////////////////////////////////////////////////////////////// -// -// Alpha TLB -// +namespace AlphaISA +{ + /////////////////////////////////////////////////////////////////////// + // + // Alpha TLB + // #ifdef DEBUG -bool uncacheBit39 = false; -bool uncacheBit40 = false; + bool uncacheBit39 = false; + bool uncacheBit40 = false; #endif #define MODE2MASK(X) (1 << (X)) -AlphaTLB::AlphaTLB(const string &name, int s) - : SimObject(name), size(s), nlu(0) -{ - table = new AlphaISA::PTE[size]; - memset(table, 0, sizeof(AlphaISA::PTE[size])); -} + TLB::TLB(const string &name, int s) + : SimObject(name), size(s), nlu(0) + { + table = new PTE[size]; + memset(table, 0, sizeof(PTE[size])); + } -AlphaTLB::~AlphaTLB() -{ - if (table) - delete [] table; -} + TLB::~TLB() + { + if (table) + delete [] table; + } -// look up an entry in the TLB -AlphaISA::PTE * -AlphaTLB::lookup(Addr vpn, uint8_t asn) const -{ - // assume not found... - AlphaISA::PTE *retval = NULL; + // look up an entry in the TLB + PTE * + TLB::lookup(Addr vpn, uint8_t asn) const + { + // assume not found... + PTE *retval = NULL; + + PageTable::const_iterator i = lookupTable.find(vpn); + 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 = pte; + break; + } - PageTable::const_iterator i = lookupTable.find(vpn); - if (i != lookupTable.end()) { - while (i->first == vpn) { - int index = i->second; - AlphaISA::PTE *pte = &table[index]; - assert(pte->valid); - if (vpn == pte->tag && (pte->asma || pte->asn == asn)) { - retval = pte; - break; + ++i; } - - ++i; } - } - DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, - retval ? "hit" : "miss", retval ? retval->ppn : 0); - return retval; -} + DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, + retval ? "hit" : "miss", retval ? retval->ppn : 0); + return retval; + } -Fault -AlphaTLB::checkCacheability(RequestPtr &req) -{ - // in Alpha, cacheability is controlled by upper-level bits of the - // physical address + Fault + TLB::checkCacheability(RequestPtr &req) + { + // in Alpha, cacheability is controlled by upper-level bits of the + // physical address - /* - * We support having the uncacheable bit in either bit 39 or bit 40. - * The Turbolaser platform (and EV5) support having the bit in 39, but - * Tsunami (which Linux assumes uses an EV6) generates accesses with - * the bit in 40. So we must check for both, but we have debug flags - * to catch a weird case where both are used, which shouldn't happen. - */ + /* + * We support having the uncacheable bit in either bit 39 or bit 40. + * The Turbolaser platform (and EV5) support having the bit in 39, but + * Tsunami (which Linux assumes uses an EV6) generates accesses with + * the bit in 40. So we must check for both, but we have debug flags + * to catch a weird case where both are used, which shouldn't happen. + */ #if ALPHA_TLASER - if (req->getPaddr() & PAddrUncachedBit39) { + if (req->getPaddr() & PAddrUncachedBit39) { #else - if (req->getPaddr() & PAddrUncachedBit43) { + if (req->getPaddr() & PAddrUncachedBit43) { #endif - // IPR memory space not implemented - if (PAddrIprSpace(req->getPaddr())) { - return new UnimpFault("IPR memory space not implemented!"); - } else { - // mark request as uncacheable - req->setFlags(req->getFlags() | UNCACHEABLE); + // IPR memory space not implemented + if (PAddrIprSpace(req->getPaddr())) { + return new UnimpFault("IPR memory space not implemented!"); + } else { + // mark request as uncacheable + req->setFlags(req->getFlags() | UNCACHEABLE); #if !ALPHA_TLASER - // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) - req->setPaddr(req->getPaddr() & PAddrUncachedMask); + // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) + req->setPaddr(req->getPaddr() & PAddrUncachedMask); #endif + } } + return NoFault; } - return NoFault; -} -// insert a new TLB entry -void -AlphaTLB::insert(Addr addr, AlphaISA::PTE &pte) -{ - AlphaISA::VAddr vaddr = addr; - if (table[nlu].valid) { - Addr oldvpn = table[nlu].tag; - PageTable::iterator i = lookupTable.find(oldvpn); + // insert a new TLB entry + void + TLB::insert(Addr addr, PTE &pte) + { + VAddr vaddr = addr; + if (table[nlu].valid) { + Addr oldvpn = table[nlu].tag; + PageTable::iterator i = lookupTable.find(oldvpn); - if (i == lookupTable.end()) - panic("TLB entry not found in lookupTable"); - - int index; - while ((index = i->second) != nlu) { - if (table[index].tag != oldvpn) + if (i == lookupTable.end()) panic("TLB entry not found in lookupTable"); - ++i; + int index; + while ((index = i->second) != nlu) { + if (table[index].tag != oldvpn) + panic("TLB entry not found in lookupTable"); + + ++i; + } + + DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); + + lookupTable.erase(i); } - DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); + DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn); - lookupTable.erase(i); - } + table[nlu] = pte; + table[nlu].tag = vaddr.vpn(); + table[nlu].valid = true; - DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn); + lookupTable.insert(make_pair(vaddr.vpn(), nlu)); + nextnlu(); + } - table[nlu] = pte; - table[nlu].tag = vaddr.vpn(); - table[nlu].valid = true; + void + TLB::flushAll() + { + DPRINTF(TLB, "flushAll\n"); + memset(table, 0, sizeof(PTE[size])); + lookupTable.clear(); + nlu = 0; + } - lookupTable.insert(make_pair(vaddr.vpn(), nlu)); - nextnlu(); -} + void + TLB::flushProcesses() + { + PageTable::iterator i = lookupTable.begin(); + PageTable::iterator end = lookupTable.end(); + while (i != end) { + int index = i->second; + PTE *pte = &table[index]; + assert(pte->valid); -void -AlphaTLB::flushAll() -{ - DPRINTF(TLB, "flushAll\n"); - memset(table, 0, sizeof(AlphaISA::PTE[size])); - lookupTable.clear(); - nlu = 0; -} + // 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; -void -AlphaTLB::flushProcesses() -{ - PageTable::iterator i = lookupTable.begin(); - PageTable::iterator end = lookupTable.end(); - while (i != end) { - int index = i->second; - AlphaISA::PTE *pte = &table[index]; - assert(pte->valid); - - // we can't increment i after we erase it, so save a copy and - // increment it to get the next entry now - PageTable::iterator cur = i; - ++i; - - if (!pte->asma) { - DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn); - pte->valid = false; - lookupTable.erase(cur); + if (!pte->asma) { + DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn); + pte->valid = false; + lookupTable.erase(cur); + } } } -} -void -AlphaTLB::flushAddr(Addr addr, uint8_t asn) -{ - AlphaISA::VAddr vaddr = addr; + void + TLB::flushAddr(Addr addr, uint8_t asn) + { + VAddr vaddr = addr; - PageTable::iterator i = lookupTable.find(vaddr.vpn()); - if (i == lookupTable.end()) - return; + PageTable::iterator i = lookupTable.find(vaddr.vpn()); + if (i == lookupTable.end()) + return; - while (i->first == vaddr.vpn()) { - int index = i->second; - AlphaISA::PTE *pte = &table[index]; - assert(pte->valid); + while (i->first == vaddr.vpn()) { + int index = i->second; + PTE *pte = &table[index]; + assert(pte->valid); - if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) { - DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), - pte->ppn); + if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) { + DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), + pte->ppn); - // invalidate this entry - pte->valid = false; + // invalidate this entry + pte->valid = false; - lookupTable.erase(i); - } + lookupTable.erase(i); + } - ++i; + ++i; + } } -} -void -AlphaTLB::serialize(ostream &os) -{ - SERIALIZE_SCALAR(size); - SERIALIZE_SCALAR(nlu); + void + TLB::serialize(ostream &os) + { + SERIALIZE_SCALAR(size); + SERIALIZE_SCALAR(nlu); - for (int i = 0; i < size; i++) { - nameOut(os, csprintf("%s.PTE%d", name(), i)); - table[i].serialize(os); + for (int i = 0; i < size; i++) { + nameOut(os, csprintf("%s.PTE%d", name(), i)); + table[i].serialize(os); + } } -} -void -AlphaTLB::unserialize(Checkpoint *cp, const string §ion) -{ - UNSERIALIZE_SCALAR(size); - UNSERIALIZE_SCALAR(nlu); + void + TLB::unserialize(Checkpoint *cp, const string §ion) + { + UNSERIALIZE_SCALAR(size); + UNSERIALIZE_SCALAR(nlu); - for (int i = 0; i < size; i++) { - table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); - if (table[i].valid) { - lookupTable.insert(make_pair(table[i].tag, i)); + for (int i = 0; i < size; i++) { + table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); + if (table[i].valid) { + lookupTable.insert(make_pair(table[i].tag, i)); + } } } -} - -/////////////////////////////////////////////////////////////////////// -// -// Alpha ITB -// -AlphaITB::AlphaITB(const std::string &name, int size) - : AlphaTLB(name, size) -{} - -void -AlphaITB::regStats() -{ - hits - .name(name() + ".hits") - .desc("ITB hits"); - misses - .name(name() + ".misses") - .desc("ITB misses"); - acv - .name(name() + ".acv") - .desc("ITB acv"); - accesses - .name(name() + ".accesses") - .desc("ITB accesses"); - - accesses = hits + misses; -} - - -Fault -AlphaITB::translate(RequestPtr &req, ThreadContext *tc) const -{ - if (AlphaISA::PcPAL(req->getVaddr())) { - // strip off PAL PC marker (lsb is 1) - req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask); - hits++; - return NoFault; + /////////////////////////////////////////////////////////////////////// + // + // Alpha ITB + // + ITB::ITB(const std::string &name, int size) + : TLB(name, size) + {} + + + void + ITB::regStats() + { + hits + .name(name() + ".hits") + .desc("ITB hits"); + misses + .name(name() + ".misses") + .desc("ITB misses"); + acv + .name(name() + ".acv") + .desc("ITB acv"); + accesses + .name(name() + ".accesses") + .desc("ITB accesses"); + + accesses = hits + misses; } - if (req->getFlags() & PHYSICAL) { - req->setPaddr(req->getVaddr()); - } else { - // verify that this is a good virtual address - if (!validVirtualAddress(req->getVaddr())) { - acv++; - return new ItbAcvFault(req->getVaddr()); + + Fault + ITB::translate(RequestPtr &req, ThreadContext *tc) const + { + if (PcPAL(req->getVaddr())) { + // strip off PAL PC marker (lsb is 1) + req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask); + hits++; + return NoFault; } + if (req->getFlags() & PHYSICAL) { + req->setPaddr(req->getVaddr()); + } else { + // verify that this is a good virtual address + if (!validVirtualAddress(req->getVaddr())) { + acv++; + return new ItbAcvFault(req->getVaddr()); + } + - // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5 - // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 + // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5 + // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 #if ALPHA_TLASER - if ((MCSR_SP(tc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) && - VAddrSpaceEV5(req->getVaddr()) == 2) { + if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) && + VAddrSpaceEV5(req->getVaddr()) == 2) { #else - if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { + if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { #endif - // only valid in kernel mode - if (ICM_CM(tc->readMiscReg(AlphaISA::IPR_ICM)) != - AlphaISA::mode_kernel) { - acv++; - return new ItbAcvFault(req->getVaddr()); - } + // only valid in kernel mode + if (ICM_CM(tc->readMiscReg(IPR_ICM)) != + mode_kernel) { + acv++; + return new ItbAcvFault(req->getVaddr()); + } - req->setPaddr(req->getVaddr() & PAddrImplMask); + req->setPaddr(req->getVaddr() & PAddrImplMask); #if !ALPHA_TLASER - // sign extend the physical address properly - if (req->getPaddr() & PAddrUncachedBit40) - req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); - else - req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); + // sign extend the physical address properly + if (req->getPaddr() & PAddrUncachedBit40) + req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); + else + req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); #endif - } else { - // not a physical address: need to look up pte - int asn = DTB_ASN_ASN(tc->readMiscReg(AlphaISA::IPR_DTB_ASN)); - AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->getVaddr()).vpn(), - asn); - - if (!pte) { - misses++; - return new ItbPageFault(req->getVaddr()); - } + } else { + // not a physical address: need to look up pte + int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN)); + PTE *pte = lookup(VAddr(req->getVaddr()).vpn(), + asn); + + if (!pte) { + misses++; + return new ItbPageFault(req->getVaddr()); + } - req->setPaddr((pte->ppn << AlphaISA::PageShift) + - (AlphaISA::VAddr(req->getVaddr()).offset() - & ~3)); + req->setPaddr((pte->ppn << PageShift) + + (VAddr(req->getVaddr()).offset() + & ~3)); - // check permissions for this access - if (!(pte->xre & - (1 << ICM_CM(tc->readMiscReg(AlphaISA::IPR_ICM))))) { - // instruction access fault - acv++; - return new ItbAcvFault(req->getVaddr()); - } + // check permissions for this access + if (!(pte->xre & + (1 << ICM_CM(tc->readMiscReg(IPR_ICM))))) { + // instruction access fault + acv++; + return new ItbAcvFault(req->getVaddr()); + } - hits++; + hits++; + } } - } - - // check that the physical address is ok (catch bad physical addresses) - if (req->getPaddr() & ~PAddrImplMask) - return genMachineCheckFault(); - return checkCacheability(req); - -} + // check that the physical address is ok (catch bad physical addresses) + if (req->getPaddr() & ~PAddrImplMask) + return genMachineCheckFault(); -/////////////////////////////////////////////////////////////////////// -// -// Alpha DTB -// -AlphaDTB::AlphaDTB(const std::string &name, int size) - : AlphaTLB(name, size) -{} + return checkCacheability(req); -void -AlphaDTB::regStats() -{ - read_hits - .name(name() + ".read_hits") - .desc("DTB read hits") - ; - - read_misses - .name(name() + ".read_misses") - .desc("DTB read misses") - ; - - read_acv - .name(name() + ".read_acv") - .desc("DTB read access violations") - ; - - read_accesses - .name(name() + ".read_accesses") - .desc("DTB read accesses") - ; - - write_hits - .name(name() + ".write_hits") - .desc("DTB write hits") - ; - - write_misses - .name(name() + ".write_misses") - .desc("DTB write misses") - ; - - write_acv - .name(name() + ".write_acv") - .desc("DTB write access violations") - ; - - write_accesses - .name(name() + ".write_accesses") - .desc("DTB write accesses") - ; - - hits - .name(name() + ".hits") - .desc("DTB hits") - ; - - misses - .name(name() + ".misses") - .desc("DTB misses") - ; - - acv - .name(name() + ".acv") - .desc("DTB access violations") - ; - - accesses - .name(name() + ".accesses") - .desc("DTB accesses") - ; - - hits = read_hits + write_hits; - misses = read_misses + write_misses; - acv = read_acv + write_acv; - accesses = read_accesses + write_accesses; -} + } -Fault -AlphaDTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const -{ - Addr pc = tc->readPC(); + /////////////////////////////////////////////////////////////////////// + // + // Alpha DTB + // + DTB::DTB(const std::string &name, int size) + : TLB(name, size) + {} + + void + DTB::regStats() + { + read_hits + .name(name() + ".read_hits") + .desc("DTB read hits") + ; + + read_misses + .name(name() + ".read_misses") + .desc("DTB read misses") + ; + + read_acv + .name(name() + ".read_acv") + .desc("DTB read access violations") + ; + + read_accesses + .name(name() + ".read_accesses") + .desc("DTB read accesses") + ; + + write_hits + .name(name() + ".write_hits") + .desc("DTB write hits") + ; + + write_misses + .name(name() + ".write_misses") + .desc("DTB write misses") + ; + + write_acv + .name(name() + ".write_acv") + .desc("DTB write access violations") + ; + + write_accesses + .name(name() + ".write_accesses") + .desc("DTB write accesses") + ; + + hits + .name(name() + ".hits") + .desc("DTB hits") + ; + + misses + .name(name() + ".misses") + .desc("DTB misses") + ; + + acv + .name(name() + ".acv") + .desc("DTB access violations") + ; + + accesses + .name(name() + ".accesses") + .desc("DTB accesses") + ; + + hits = read_hits + write_hits; + misses = read_misses + write_misses; + acv = read_acv + write_acv; + accesses = read_accesses + write_accesses; + } - AlphaISA::mode_type mode = - (AlphaISA::mode_type)DTB_CM_CM(tc->readMiscReg(AlphaISA::IPR_DTB_CM)); + Fault + DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const + { + Addr pc = tc->readPC(); + mode_type mode = + (mode_type)DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM)); - /** - * Check for alignment faults - */ - if (req->getVaddr() & (req->getSize() - 1)) { - DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(), - req->getSize()); - uint64_t flags = write ? MM_STAT_WR_MASK : 0; - return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags); - } - if (pc & 0x1) { - mode = (req->getFlags() & ALTMODE) ? - (AlphaISA::mode_type)ALT_MODE_AM( - tc->readMiscReg(AlphaISA::IPR_ALT_MODE)) - : AlphaISA::mode_kernel; - } + /** + * Check for alignment faults + */ + if (req->getVaddr() & (req->getSize() - 1)) { + DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(), + req->getSize()); + uint64_t flags = write ? MM_STAT_WR_MASK : 0; + return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags); + } - if (req->getFlags() & PHYSICAL) { - req->setPaddr(req->getVaddr()); - } else { - // verify that this is a good virtual address - if (!validVirtualAddress(req->getVaddr())) { - if (write) { write_acv++; } else { read_acv++; } - uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | - MM_STAT_BAD_VA_MASK | - MM_STAT_ACV_MASK; - return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); + if (pc & 0x1) { + mode = (req->getFlags() & ALTMODE) ? + (mode_type)ALT_MODE_AM( + tc->readMiscReg(IPR_ALT_MODE)) + : mode_kernel; } - // Check for "superpage" mapping + if (req->getFlags() & PHYSICAL) { + req->setPaddr(req->getVaddr()); + } else { + // verify that this is a good virtual address + if (!validVirtualAddress(req->getVaddr())) { + if (write) { write_acv++; } else { read_acv++; } + uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | + MM_STAT_BAD_VA_MASK | + MM_STAT_ACV_MASK; + return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); + } + + // Check for "superpage" mapping #if ALPHA_TLASER - if ((MCSR_SP(tc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) && - VAddrSpaceEV5(req->getVaddr()) == 2) { + if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) && + VAddrSpaceEV5(req->getVaddr()) == 2) { #else - if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { + if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { #endif - // only valid in kernel mode - if (DTB_CM_CM(tc->readMiscReg(AlphaISA::IPR_DTB_CM)) != - AlphaISA::mode_kernel) { - if (write) { write_acv++; } else { read_acv++; } - uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) | - MM_STAT_ACV_MASK); - return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); - } + // only valid in kernel mode + if (DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM)) != + mode_kernel) { + if (write) { write_acv++; } else { read_acv++; } + uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) | + MM_STAT_ACV_MASK); + return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); + } - req->setPaddr(req->getVaddr() & PAddrImplMask); + req->setPaddr(req->getVaddr() & PAddrImplMask); #if !ALPHA_TLASER - // sign extend the physical address properly - if (req->getPaddr() & PAddrUncachedBit40) - req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); - else - req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); + // sign extend the physical address properly + if (req->getPaddr() & PAddrUncachedBit40) + req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); + else + req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); #endif - } else { - if (write) - write_accesses++; - else - read_accesses++; - - int asn = DTB_ASN_ASN(tc->readMiscReg(AlphaISA::IPR_DTB_ASN)); - - // not a physical address: need to look up pte - AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->getVaddr()).vpn(), - asn); - - if (!pte) { - // page fault - if (write) { write_misses++; } else { read_misses++; } - uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | - MM_STAT_DTB_MISS_MASK; - return (req->getFlags() & VPTE) ? - (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(), - flags)) : - (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(), - flags)); - } - - req->setPaddr((pte->ppn << AlphaISA::PageShift) + - AlphaISA::VAddr(req->getVaddr()).offset()); - - if (write) { - if (!(pte->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); - return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); - } - if (pte->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))) { - read_acv++; - uint64_t flags = MM_STAT_ACV_MASK | - (pte->fonr ? MM_STAT_FONR_MASK : 0); - return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); + if (write) + write_accesses++; + else + read_accesses++; + + int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN)); + + // not a physical address: need to look up pte + PTE *pte = lookup(VAddr(req->getVaddr()).vpn(), + asn); + + if (!pte) { + // page fault + if (write) { write_misses++; } else { read_misses++; } + uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | + MM_STAT_DTB_MISS_MASK; + return (req->getFlags() & VPTE) ? + (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(), + flags)) : + (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(), + flags)); } - if (pte->fonr) { - read_acv++; - uint64_t flags = MM_STAT_FONR_MASK; - return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); + + req->setPaddr((pte->ppn << PageShift) + + VAddr(req->getVaddr()).offset()); + + if (write) { + if (!(pte->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); + return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); + } + if (pte->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))) { + read_acv++; + uint64_t flags = MM_STAT_ACV_MASK | + (pte->fonr ? MM_STAT_FONR_MASK : 0); + return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); + } + if (pte->fonr) { + read_acv++; + uint64_t flags = MM_STAT_FONR_MASK; + return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); + } } } + + if (write) + write_hits++; + else + read_hits++; } - if (write) - write_hits++; - else - read_hits++; + // check that the physical address is ok (catch bad physical addresses) + if (req->getPaddr() & ~PAddrImplMask) + return genMachineCheckFault(); + + return checkCacheability(req); } - // check that the physical address is ok (catch bad physical addresses) - if (req->getPaddr() & ~PAddrImplMask) - return genMachineCheckFault(); + PTE & + TLB::index(bool advance) + { + PTE *pte = &table[nlu]; - return checkCacheability(req); -} + if (advance) + nextnlu(); -AlphaISA::PTE & -AlphaTLB::index(bool advance) -{ - AlphaISA::PTE *pte = &table[nlu]; + return *pte; + } - if (advance) - nextnlu(); + DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", TLB) - return *pte; -} + BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) -DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB) + Param<int> size; -BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB) + END_DECLARE_SIM_OBJECT_PARAMS(ITB) - Param<int> size; + BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) -END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB) + INIT_PARAM_DFLT(size, "TLB size", 48) -BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB) + END_INIT_SIM_OBJECT_PARAMS(ITB) - INIT_PARAM_DFLT(size, "TLB size", 48) - -END_INIT_SIM_OBJECT_PARAMS(AlphaITB) + CREATE_SIM_OBJECT(ITB) + { + return new ITB(getInstanceName(), size); + } -CREATE_SIM_OBJECT(AlphaITB) -{ - return new AlphaITB(getInstanceName(), size); -} + REGISTER_SIM_OBJECT("AlphaITB", ITB) -REGISTER_SIM_OBJECT("AlphaITB", AlphaITB) + BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) -BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB) + Param<int> size; - Param<int> size; + END_DECLARE_SIM_OBJECT_PARAMS(DTB) -END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB) + BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) -BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB) + INIT_PARAM_DFLT(size, "TLB size", 64) - INIT_PARAM_DFLT(size, "TLB size", 64) + END_INIT_SIM_OBJECT_PARAMS(DTB) -END_INIT_SIM_OBJECT_PARAMS(AlphaDTB) + CREATE_SIM_OBJECT(DTB) + { + return new DTB(getInstanceName(), size); + } -CREATE_SIM_OBJECT(AlphaDTB) -{ - return new AlphaDTB(getInstanceName(), size); + REGISTER_SIM_OBJECT("AlphaDTB", DTB) } - -REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB) - diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index 955460649..ea5ba5539 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -36,6 +36,7 @@ #include "arch/alpha/ev5.hh" #include "arch/alpha/isa_traits.hh" +#include "arch/alpha/pagetable.hh" #include "arch/alpha/utility.hh" #include "arch/alpha/vtophys.hh" #include "base/statistics.hh" @@ -45,82 +46,87 @@ class ThreadContext; -class AlphaTLB : public SimObject +namespace AlphaISA { - protected: - typedef std::multimap<Addr, int> PageTable; - PageTable lookupTable; // Quick lookup into page table - - AlphaISA::PTE *table; // the Page Table - int size; // TLB Size - int nlu; // not last used entry (for replacement) - - void nextnlu() { if (++nlu >= size) nlu = 0; } - AlphaISA::PTE *lookup(Addr vpn, uint8_t asn) const; - - public: - AlphaTLB(const std::string &name, int size); - virtual ~AlphaTLB(); - - int getsize() const { return size; } - - AlphaISA::PTE &index(bool advance = true); - void insert(Addr vaddr, AlphaISA::PTE &pte); - - void flushAll(); - void flushProcesses(); - void flushAddr(Addr addr, uint8_t asn); - - // static helper functions... really EV5 VM traits - static bool validVirtualAddress(Addr vaddr) { - // unimplemented bits must be all 0 or all 1 - Addr unimplBits = vaddr & EV5::VAddrUnImplMask; - return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask); - } - - static Fault checkCacheability(RequestPtr &req); - - // Checkpointing - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); -}; - -class AlphaITB : public AlphaTLB -{ - protected: - mutable Stats::Scalar<> hits; - mutable Stats::Scalar<> misses; - mutable Stats::Scalar<> acv; - mutable Stats::Formula accesses; - - public: - AlphaITB(const std::string &name, int size); - virtual void regStats(); - - Fault translate(RequestPtr &req, ThreadContext *tc) const; -}; - -class AlphaDTB : public AlphaTLB -{ - protected: - mutable Stats::Scalar<> read_hits; - mutable Stats::Scalar<> read_misses; - mutable Stats::Scalar<> read_acv; - mutable Stats::Scalar<> read_accesses; - mutable Stats::Scalar<> write_hits; - mutable Stats::Scalar<> write_misses; - mutable Stats::Scalar<> write_acv; - mutable Stats::Scalar<> write_accesses; - Stats::Formula hits; - Stats::Formula misses; - Stats::Formula acv; - Stats::Formula accesses; - - public: - AlphaDTB(const std::string &name, int size); - virtual void regStats(); - - Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const; -}; + class PTE; + + class TLB : public SimObject + { + protected: + typedef std::multimap<Addr, int> PageTable; + PageTable lookupTable; // Quick lookup into page table + + PTE *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) const; + + public: + TLB(const std::string &name, int size); + virtual ~TLB(); + + int getsize() const { return size; } + + PTE &index(bool advance = true); + void insert(Addr vaddr, PTE &pte); + + void flushAll(); + void flushProcesses(); + void flushAddr(Addr addr, uint8_t asn); + + // static helper functions... really EV5 VM traits + static bool validVirtualAddress(Addr vaddr) { + // unimplemented bits must be all 0 or all 1 + Addr unimplBits = vaddr & EV5::VAddrUnImplMask; + return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask); + } + + static Fault checkCacheability(RequestPtr &req); + + // Checkpointing + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + }; + + class ITB : public TLB + { + protected: + mutable Stats::Scalar<> hits; + mutable Stats::Scalar<> misses; + mutable Stats::Scalar<> acv; + mutable Stats::Formula accesses; + + public: + ITB(const std::string &name, int size); + virtual void regStats(); + + Fault translate(RequestPtr &req, ThreadContext *tc) const; + }; + + class DTB : public TLB + { + protected: + mutable Stats::Scalar<> read_hits; + mutable Stats::Scalar<> read_misses; + mutable Stats::Scalar<> read_acv; + mutable Stats::Scalar<> read_accesses; + mutable Stats::Scalar<> write_hits; + mutable Stats::Scalar<> write_misses; + mutable Stats::Scalar<> write_acv; + mutable Stats::Scalar<> write_accesses; + Stats::Formula hits; + Stats::Formula misses; + Stats::Formula acv; + Stats::Formula accesses; + + public: + DTB(const std::string &name, int size); + virtual void regStats(); + + Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const; + }; +} #endif // __ALPHA_MEMORY_HH__ diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 0304d1c3a..100736555 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -42,12 +42,18 @@ namespace AlphaISA { + static inline bool + inUserMode(ThreadContext *tc) + { + return (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + } + static inline ExtMachInst - makeExtMI(MachInst inst, ThreadContext * xc) { + makeExtMI(MachInst inst, Addr pc) { #if FULL_SYSTEM ExtMachInst ext_inst = inst; - if (xc->readPC() && 0x1) - return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32); + if (pc && 0x1) + return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); else return ext_inst; #else |