diff options
Diffstat (limited to 'src/arch/sparc')
-rw-r--r-- | src/arch/sparc/SConscript | 2 | ||||
-rw-r--r-- | src/arch/sparc/asi.hh | 2 | ||||
-rw-r--r-- | src/arch/sparc/faults.cc | 41 | ||||
-rw-r--r-- | src/arch/sparc/faults.hh | 8 | ||||
-rw-r--r-- | src/arch/sparc/interrupts.hh | 92 | ||||
-rw-r--r-- | src/arch/sparc/miscregfile.cc | 147 | ||||
-rw-r--r-- | src/arch/sparc/miscregfile.hh | 6 | ||||
-rw-r--r-- | src/arch/sparc/remote_gdb.cc | 456 | ||||
-rw-r--r-- | src/arch/sparc/remote_gdb.hh | 129 | ||||
-rw-r--r-- | src/arch/sparc/system.cc | 13 | ||||
-rw-r--r-- | src/arch/sparc/system.hh | 2 | ||||
-rw-r--r-- | src/arch/sparc/utility.hh | 7 | ||||
-rw-r--r-- | src/arch/sparc/vtophys.cc | 132 |
13 files changed, 857 insertions, 180 deletions
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index e317502e0..5843058a4 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -54,8 +54,8 @@ base_sources = Split(''' # Full-system sources full_system_sources = Split(''' - ua2005.cc vtophys.cc + system.cc ''') # Syscall emulation (non-full-system) sources diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh index 876567225..6677b23df 100644 --- a/src/arch/sparc/asi.hh +++ b/src/arch/sparc/asi.hh @@ -219,4 +219,4 @@ namespace SparcISA }; -#endif // __ARCH_SPARC_TLB_HH__ +#endif // __ARCH_SPARC_ASI_HH__ diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 567ca5f5c..da7fc730d 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -33,12 +33,13 @@ #include "arch/sparc/faults.hh" #include "arch/sparc/isa_traits.hh" -#include "arch/sparc/process.hh" #include "base/bitfield.hh" #include "base/trace.hh" +#include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #if !FULL_SYSTEM +#include "arch/sparc/process.hh" #include "mem/page_table.hh" #include "sim/process.hh" #endif @@ -361,15 +362,43 @@ void SparcFault::invoke(ThreadContext * tc) //Use the SPARC trap state machine } +void PowerOnReset::invoke(ThreadContext * tc) +{ + //For SPARC, when a system is first started, there is a power + //on reset Trap which sets the processor into the following state. + //Bits that aren't set aren't defined on startup. + /* + tl = MaxTL; + gl = MaxGL; + + tickFields.counter = 0; //The TICK register is unreadable bya + tickFields.npt = 1; //The TICK register is unreadable by by !priv + + softint = 0; // Clear all the soft interrupt bits + tick_cmprFields.int_dis = 1; // disable timer compare interrupts + tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + stickFields.npt = 1; //The TICK register is unreadable by by !priv + stick_cmprFields.int_dis = 1; // disable timer compare interrupts + stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + + tt[tl] = _trapType; + pstate = 0; // fields 0 but pef + pstateFields.pef = 1; + + hpstate = 0; + hpstateFields.red = 1; + hpstateFields.hpriv = 1; + hpstateFields.tlz = 0; // this is a guess + hintp = 0; // no interrupts pending + hstick_cmprFields.int_dis = 1; // disable timer compare interrupts + hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + */ +} + #endif #if !FULL_SYSTEM -void TrapInstruction::invoke(ThreadContext * tc) -{ - // Should be handled in ISA. -} - void SpillNNormal::invoke(ThreadContext *tc) { doNormalFault(tc, trapType()); diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh index 394a06294..0c7106707 100644 --- a/src/arch/sparc/faults.hh +++ b/src/arch/sparc/faults.hh @@ -130,6 +130,7 @@ class PowerOnReset : public SparcFault TrapType trapType() {return _trapType;} FaultPriority priority() {return _priority;} FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); }; class WatchDogReset : public SparcFault @@ -603,17 +604,12 @@ class TrapInstruction : public EnumeratedFault static TrapType _baseTrapType; static FaultPriority _priority; static FaultStat _count; - uint64_t syscall_num; TrapType baseTrapType() {return _baseTrapType;} public: - TrapInstruction(uint32_t n, uint64_t syscall) : - EnumeratedFault(n), syscall_num(syscall) {;} + TrapInstruction(int32_t n) : EnumeratedFault(n) {;} FaultName name() {return _name;} FaultPriority priority() {return _priority;} FaultStat & countStat() {return _count;} -#if !FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif }; diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh new file mode 100644 index 000000000..0072f4184 --- /dev/null +++ b/src/arch/sparc/interrupts.hh @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_SPARC_INTERRUPT_HH__ +#define __ARCH_SPARC_INTERRUPT_HH__ + +#include "arch/sparc/faults.hh" + +namespace SparcISA +{ + class Interrupts + { + protected: + Fault interrupts[NumInterruptLevels]; + bool requested[NumInterruptLevels]; + + public: + Interrupts() + { + for(int x = 0; x < NumInterruptLevels; x++) + { + interrupts[x] = new InterruptLevelN(x); + requested[x] = false; + } + } + void post(int int_num, int index) + { + if(int_num < 0 || int_num >= NumInterruptLevels) + panic("int_num out of bounds\n"); + + requested[int_num] = true; + } + + void clear(int int_num, int index) + { + requested[int_num] = false; + } + + void clear_all() + { + for(int x = 0; x < NumInterruptLevels; x++) + requested[x] = false; + } + + bool check_interrupts(ThreadContext * tc) const + { + return true; + } + + Fault getInterrupt(ThreadContext * tc) + { + return NoFault; + } + + void serialize(std::ostream &os) + { + } + + void unserialize(Checkpoint *cp, const std::string §ion) + { + } + }; +} + +#endif // __ARCH_SPARC_INTERRUPT_HH__ diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 2f3cfb417..217fba0bd 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -31,9 +31,14 @@ #include "arch/sparc/miscregfile.hh" #include "base/trace.hh" +#include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" +#if FULL_SYSTEM +#include "arch/sparc/system.hh" +#endif + using namespace SparcISA; using namespace std; @@ -55,51 +60,8 @@ string SparcISA::getMiscRegName(RegIndex index) return miscRegName[index]; } -#if FULL_SYSTEM - -//XXX These need an implementation someplace -/** Fullsystem only register version of ReadRegWithEffect() */ -MiscReg MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext *tc); -/** Fullsystem only register version of SetRegWithEffect() */ -void MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext * tc); -#endif - void MiscRegFile::reset() { - //pstateFields.pef = 0; //No FPU - //pstateFields.pef = 1; //FPU -#if FULL_SYSTEM - //For SPARC, when a system is first started, there is a power - //on reset Trap which sets the processor into the following state. - //Bits that aren't set aren't defined on startup. - //XXX this code should be moved into the POR fault. - tl = MaxTL; - gl = MaxGL; - - tickFields.counter = 0; //The TICK register is unreadable bya - tickFields.npt = 1; //The TICK register is unreadable by by !priv - - softint = 0; // Clear all the soft interrupt bits - tick_cmprFields.int_dis = 1; // disable timer compare interrupts - tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - stickFields.npt = 1; //The TICK register is unreadable by by !priv - stick_cmprFields.int_dis = 1; // disable timer compare interrupts - stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - - - tt[tl] = power_on_reset; - pstate = 0; // fields 0 but pef - pstateFields.pef = 1; - - hpstate = 0; - hpstateFields.red = 1; - hpstateFields.hpriv = 1; - hpstateFields.tlz = 0; // this is a guess - hintp = 0; // no interrupts pending - hstick_cmprFields.int_dis = 1; // disable timer compare interrupts - hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing -#endif } MiscReg MiscRegFile::readReg(int miscReg) @@ -199,10 +161,20 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) case MISCREG_PCR: case MISCREG_PIC: panic("Performance Instrumentation not impl\n"); - /** Floating Point Status Register */ case MISCREG_FSR: panic("Floating Point not implemented\n"); +//We'll include this only in FS so we don't need the SparcSystem type around +//in SE. +#if FULL_SYSTEM + case MISCREG_STICK: + SparcSystem *sys; + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + return curTick/Clock::Int::ns - sys->sysTick | stickFields.npt << 63; +#endif + case MISCREG_HVER: + return NWindows | MaxTL << 8 | MaxGL << 16; } return readReg(miscReg); } @@ -350,6 +322,10 @@ void MiscRegFile::setRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc) { const uint64_t Bit64 = (1ULL << 63); +#if FULL_SYSTEM + uint64_t time; + SparcSystem *sys; +#endif switch (miscReg) { case MISCREG_TICK: tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64; @@ -375,6 +351,70 @@ void MiscRegFile::setRegWithEffect(int miscReg, case MISCREG_GL: tc->changeRegFileContext(CONTEXT_GLOBALS, val); break; + case MISCREG_SOFTINT: + //We need to inject interrupts, and or notify the interrupt + //object that it needs to use a different interrupt level. + //Any newly appropriate interrupts will happen when the cpu gets + //around to checking for them. This might not be quite what we + //want. + break; + case MISCREG_SOFTINT_CLR: + //Do whatever this is supposed to do... + break; + case MISCREG_SOFTINT_SET: + //Do whatever this is supposed to do... + break; +#if FULL_SYSTEM + case MISCREG_TICK_CMPR: + if (tickCompare == NULL) + tickCompare = new TickCompareEvent(this, tc); + setReg(miscReg, val); + if (tick_cmprFields.int_dis && tickCompare->scheduled()) + tickCompare->deschedule(); + time = tick_cmprFields.tick_cmpr - tickFields.counter; + if (!tick_cmprFields.int_dis && time > 0) + tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); + break; +#endif + case MISCREG_PIL: + //We need to inject interrupts, and or notify the interrupt + //object that it needs to use a different interrupt level. + //Any newly appropriate interrupts will happen when the cpu gets + //around to checking for them. This might not be quite what we + //want. + break; +//We'll include this only in FS so we don't need the SparcSystem type around +//in SE. +#if FULL_SYSTEM + case MISCREG_STICK: + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + sys->sysTick = curTick/Clock::Int::ns - val & ~Bit64; + stickFields.npt = val & Bit64 ? 1 : 0; + break; + case MISCREG_STICK_CMPR: + if (sTickCompare == NULL) + sTickCompare = new STickCompareEvent(this, tc); + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + if (stick_cmprFields.int_dis && sTickCompare->scheduled()) + sTickCompare->deschedule(); + time = stick_cmprFields.tick_cmpr - sys->sysTick; + if (!stick_cmprFields.int_dis && time > 0) + sTickCompare->schedule(time * Clock::Int::ns); + break; + case MISCREG_HSTICK_CMPR: + if (hSTickCompare == NULL) + hSTickCompare = new HSTickCompareEvent(this, tc); + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + if (hstick_cmprFields.int_dis && hSTickCompare->scheduled()) + hSTickCompare->deschedule(); + int64_t time = hstick_cmprFields.tick_cmpr - sys->sysTick; + if (!hstick_cmprFields.int_dis && time > 0) + hSTickCompare->schedule(time * Clock::Int::ns); + break; +#endif } setReg(miscReg, val); } @@ -444,3 +484,22 @@ void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) implicitDataAsi = (ASI)temp; } +#if FULL_SYSTEM +void +MiscRegFile::processTickCompare(ThreadContext *tc) +{ + panic("tick compare not implemented\n"); +} + +void +MiscRegFile::processSTickCompare(ThreadContext *tc) +{ + panic("tick compare not implemented\n"); +} + +void +MiscRegFile::processHSTickCompare(ThreadContext *tc) +{ + panic("tick compare not implemented\n"); +} +#endif diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index ac1ad90b9..0e424dbd2 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -354,12 +354,6 @@ namespace SparcISA typedef CpuEventWrapper<MiscRegFile, &MiscRegFile::processHSTickCompare> HSTickCompareEvent; HSTickCompareEvent *hSTickCompare; - - /** Fullsystem only register version of ReadRegWithEffect() */ - MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); - /** Fullsystem only register version of SetRegWithEffect() */ - Fault setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext * tc); #endif public: diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc new file mode 100644 index 000000000..2e662af7f --- /dev/null +++ b/src/arch/sparc/remote_gdb.cc @@ -0,0 +1,456 @@ +/* + * 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/vtophys.hh" +#include "arch/sparc/remote_gdb.hh" +#include "base/intmath.hh" +#include "base/kgdb.h" +#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::Event::Event(RemoteGDB *g, int fd, int e) + : PollEvent(fd, e), gdb(g) +{} + +void +RemoteGDB::Event::process(int revent) +{ + if (revent & POLLIN) + gdb->trap(ALPHA_KENTRY_IF); + else if (revent & POLLNVAL) + gdb->detach(); +} + +RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) + : BaseRemoteGDB(_system, c, KGDB_NUMREGS), + event(NULL) +{} + +RemoteGDB::~RemoteGDB() +{ + if (event) + delete event; +} + +/////////////////////////////////////////////////////////// +// 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::signal +// +// Translate a trap number into a Unix-compatible signal number. +// (GDB only understands Unix signal numbers.) +// +int +RemoteGDB::signal(int type) +{ + switch (type) { + case ALPHA_KENTRY_INT: + return (SIGTRAP); + + case ALPHA_KENTRY_UNA: + return (SIGBUS); + + case ALPHA_KENTRY_ARITH: + return (SIGFPE); + + case ALPHA_KENTRY_IF: + return (SIGILL); + + case ALPHA_KENTRY_MM: + return (SIGSEGV); + + default: + panic("unknown signal type"); + return 0; + } +} + +/////////////////////////////////////////////////////////// +// RemoteGDB::getregs +// +// Translate the kernel debugger register format into +// the GDB register format. +void +RemoteGDB::getregs() +{ + memset(gdbregs.regs, 0, gdbregs.size); + + 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::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr) +{ + DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr); + + bkpt.address = addr; + insertHardBreak(addr, 4); +} + +void +RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt) +{ + DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", + bkpt.address); + + + removeHardBreak(bkpt.address, 4); + bkpt.address = 0; +} + +void +RemoteGDB::clearSingleStep() +{ + DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n", + takenBkpt.address, notTakenBkpt.address); + + if (takenBkpt.address != 0) + clearTempBreakpoint(takenBkpt); + + if (notTakenBkpt.address != 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.address, notTakenBkpt.address); + + 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; + } +} + + +PCEventQueue *RemoteGDB::getPcEventQueue() +{ + return &system->pcEventQueue; +} + + +RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc) + : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc), + gdb(_gdb), refcount(0) +{ + DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc); +} + +void +RemoteGDB::HardBreakpoint::process(ThreadContext *tc) +{ + DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc()); + + if (tc == gdb->context) + gdb->trap(ALPHA_KENTRY_INT); +} + +bool +RemoteGDB::insertSoftBreak(Addr addr, size_t len) +{ + if (len != sizeof(MachInst)) + panic("invalid length\n"); + + return insertHardBreak(addr, len); +} + +bool +RemoteGDB::removeSoftBreak(Addr addr, size_t len) +{ + if (len != sizeof(MachInst)) + panic("invalid length\n"); + + return removeHardBreak(addr, len); +} + +bool +RemoteGDB::insertHardBreak(Addr addr, size_t len) +{ + if (len != sizeof(MachInst)) + panic("invalid length\n"); + + DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr); + + HardBreakpoint *&bkpt = hardBreakMap[addr]; + if (bkpt == 0) + bkpt = new HardBreakpoint(this, addr); + + bkpt->refcount++; + + return true; +} + +bool +RemoteGDB::removeHardBreak(Addr addr, size_t len) +{ + if (len != sizeof(MachInst)) + panic("invalid length\n"); + + DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr); + + break_iter_t i = hardBreakMap.find(addr); + if (i == hardBreakMap.end()) + return false; + + HardBreakpoint *hbp = (*i).second; + if (--hbp->refcount == 0) { + delete hbp; + hardBreakMap.erase(i); + } + + return true; +} diff --git a/src/arch/sparc/remote_gdb.hh b/src/arch/sparc/remote_gdb.hh new file mode 100644 index 000000000..6ac4f296f --- /dev/null +++ b/src/arch/sparc/remote_gdb.hh @@ -0,0 +1,129 @@ +/* + * 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/types.hh" +#include "base/remote_gdb.hh" +#include "cpu/pc_event.hh" +#include "base/pollevent.hh" + +class System; +class ThreadContext; +class PhysicalMemory; + +namespace SparcISA +{ + class RemoteGDB : public BaseRemoteGDB + { + private: + friend void debugger(); + friend class GDBListener; + + protected: + class Event : public PollEvent + { + protected: + RemoteGDB *gdb; + + public: + Event(RemoteGDB *g, int fd, int e); + void process(int revent); + }; + + friend class Event; + Event *event; + + protected: + // Machine memory + bool write(Addr addr, size_t size, const char *data); + + public: + RemoteGDB(System *system, ThreadContext *context); + ~RemoteGDB(); + + bool acc(Addr addr, size_t len); + int signal(int type); + + protected: + void getregs(); + void setregs(); + + void clearSingleStep(); + void setSingleStep(); + + PCEventQueue *getPcEventQueue(); + + protected: + class HardBreakpoint : public PCEvent + { + private: + RemoteGDB *gdb; + + public: + int refcount; + + public: + HardBreakpoint(RemoteGDB *_gdb, Addr addr); + std::string name() { return gdb->name() + ".hwbkpt"; } + + virtual void process(ThreadContext *tc); + }; + friend class HardBreakpoint; + + typedef std::map<Addr, HardBreakpoint *> break_map_t; + typedef break_map_t::iterator break_iter_t; + break_map_t hardBreakMap; + + bool insertSoftBreak(Addr addr, size_t len); + bool removeSoftBreak(Addr addr, size_t len); + bool insertHardBreak(Addr addr, size_t len); + bool removeHardBreak(Addr addr, size_t len); + + protected: + struct TempBreakpoint { + Addr address; // set here + MachInst bkpt_inst; // saved instruction at bkpt + int init_count; // number of times to skip bkpt + int count; // current count + }; + + TempBreakpoint notTakenBkpt; + TempBreakpoint takenBkpt; + + void clearTempBreakpoint(TempBreakpoint &bkpt); + void setTempBreakpoint(TempBreakpoint &bkpt, Addr addr); + }; +} + +#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */ diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index ef6443d17..952ac2deb 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -77,7 +77,7 @@ SparcSystem::SparcSystem(Params *p) hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask); // load symbols - if (!reset->loadGlobalSymbols(reset)) + if (!reset->loadGlobalSymbols(resetSymtab)) panic("could not load reset symbols\n"); if (!openboot->loadGlobalSymbols(openbootSymtab)) @@ -148,7 +148,10 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) Param<std::string> hypervisor_bin; Param<std::string> openboot_bin; + Param<Tick> boot_cpu_frequency; Param<std::string> boot_osflags; + Param<uint64_t> system_type; + Param<uint64_t> system_rev; Param<std::string> readfile; Param<unsigned int> init_param; @@ -156,7 +159,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) - INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", System::MemoryModeStrings), @@ -164,12 +166,13 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) INIT_PARAM(reset_bin, "file that contains the reset code"), INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"), INIT_PARAM(openboot_bin, "file that contains the openboot code"), + INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", "a"), - INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), - INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10) + INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), + INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), + INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0) END_INIT_SIM_OBJECT_PARAMS(SparcSystem) diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh index 614707f6c..3c8c6327e 100644 --- a/src/arch/sparc/system.hh +++ b/src/arch/sparc/system.hh @@ -46,7 +46,7 @@ class SparcSystem : public System struct Params : public System::Params { std::string reset_bin; - std::string hypervison_bin; + std::string hypervisor_bin; std::string openboot_bin; std::string boot_osflags; uint64_t system_type; diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 23fddf0e9..e2b0b2307 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -31,6 +31,7 @@ #ifndef __ARCH_SPARC_UTILITY_HH__ #define __ARCH_SPARC_UTILITY_HH__ +#include "arch/sparc/faults.hh" #include "arch/sparc/isa_traits.hh" #include "base/misc.hh" #include "base/bitfield.hh" @@ -99,6 +100,12 @@ namespace SparcISA template <class TC> void zeroRegisters(TC *tc); + inline void initCPU(ThreadContext *tc, int cpuId) + { + static Fault por = new PowerOnReset(); + por->invoke(tc); + } + } // namespace SparcISA #endif diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc index f7fd92c15..429126b70 100644 --- a/src/arch/sparc/vtophys.cc +++ b/src/arch/sparc/vtophys.cc @@ -32,135 +32,47 @@ #include <string> -#include "arch/alpha/ev5.hh" -#include "arch/alpha/vtophys.hh" +#include "arch/sparc/vtophys.hh" #include "base/chunk_generator.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" #include "mem/vport.hh" using namespace std; -using namespace AlphaISA; -AlphaISA::PageTableEntry -AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr) +namespace SparcISA { - Addr level1_pte = ptbr + vaddr.level1(); - AlphaISA::PageTableEntry level1 = mem->read<uint64_t>(level1_pte); - if (!level1.valid()) { - DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr); - return 0; + PageTableEntry kernel_pte_lookup(FunctionalPort *mem, + Addr ptbr, VAddr vaddr) + { + PageTableEntry pte(4); + return pte; } - Addr level2_pte = level1.paddr() + vaddr.level2(); - AlphaISA::PageTableEntry level2 = mem->read<uint64_t>(level2_pte); - if (!level2.valid()) { - DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr); - return 0; + Addr vtophys(Addr vaddr) + { + return vaddr; } - Addr level3_pte = level2.paddr() + vaddr.level3(); - AlphaISA::PageTableEntry level3 = mem->read<uint64_t>(level3_pte); - if (!level3.valid()) { - DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr); - return 0; + Addr vtophys(ThreadContext *tc, Addr addr) + { + return addr; } - return level3; -} -Addr -AlphaISA::vtophys(Addr vaddr) -{ - Addr paddr = 0; - if (AlphaISA::IsUSeg(vaddr)) - DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr); - else if (AlphaISA::IsK0Seg(vaddr)) - paddr = AlphaISA::K0Seg2Phys(vaddr); - else - panic("vtophys: ptbr is not set on virtual lookup"); - DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); - - return paddr; -} - -Addr -AlphaISA::vtophys(ThreadContext *tc, Addr addr) -{ - AlphaISA::VAddr vaddr = addr; - Addr ptbr = tc->readMiscReg(AlphaISA::IPR_PALtemp20); - Addr paddr = 0; - //@todo Andrew couldn't remember why he commented some of this code - //so I put it back in. Perhaps something to do with gdb debugging? - if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) { - paddr = vaddr & ~ULL(1); - } else { - if (AlphaISA::IsK0Seg(vaddr)) { - paddr = AlphaISA::K0Seg2Phys(vaddr); - } else if (!ptbr) { - paddr = vaddr; - } else { - AlphaISA::PageTableEntry pte = - kernel_pte_lookup(tc->getPhysPort(), ptbr, vaddr); - if (pte.valid()) - paddr = pte.paddr() | vaddr.offset(); - } + void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) + { } + void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) + { + } - DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); - - return paddr; -} - - -void -AlphaISA::CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) -{ - uint8_t *dst = (uint8_t *)dest; - VirtualPort *vp = tc->getVirtPort(tc); - - vp->readBlob(src, dst, cplen); - - tc->delVirtPort(vp); - -} - -void -AlphaISA::CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) -{ - uint8_t *src = (uint8_t *)source; - VirtualPort *vp = tc->getVirtPort(tc); - - vp->writeBlob(dest, src, cplen); - - tc->delVirtPort(vp); -} - -void -AlphaISA::CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) -{ - int len = 0; - VirtualPort *vp = tc->getVirtPort(tc); - - do { - vp->readBlob(vaddr++, (uint8_t*)dst++, 1); - len++; - } while (len < maxlen && dst[len] != 0 ); - - tc->delVirtPort(vp); - dst[len] = 0; -} + void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) + { + } -void -AlphaISA::CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) -{ - VirtualPort *vp = tc->getVirtPort(tc); - for (ChunkGenerator gen(vaddr, strlen(src), AlphaISA::PageBytes); !gen.done(); - gen.next()) + void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) { - vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size()); - src += gen.size(); } - tc->delVirtPort(vp); } |