diff options
Diffstat (limited to 'src')
81 files changed, 2107 insertions, 857 deletions
diff --git a/src/SConscript b/src/SConscript index d938d533f..b383f58d6 100644 --- a/src/SConscript +++ b/src/SConscript @@ -211,31 +211,6 @@ full_system_sources = Split(''' cpu/intr_control.cc cpu/profile.cc - dev/alpha_console.cc - dev/baddev.cc - dev/disk_image.cc - dev/etherbus.cc - dev/etherdump.cc - dev/etherint.cc - dev/etherlink.cc - dev/etherpkt.cc - dev/ethertap.cc - dev/ide_ctrl.cc - dev/ide_disk.cc - dev/io_device.cc - dev/isa_fake.cc - dev/ns_gige.cc - dev/pciconfigall.cc - dev/pcidev.cc - dev/pktfifo.cc - dev/platform.cc - dev/simconsole.cc - dev/simple_disk.cc - dev/tsunami.cc - dev/tsunami_cchip.cc - dev/tsunami_io.cc - dev/tsunami_pchip.cc - dev/uart.cc dev/uart8250.cc @@ -252,7 +227,6 @@ full_system_sources = Split(''' #dev/sinic.cc #dev/i8254xGBe.cc - if env['TARGET_ISA'] == 'alpha': full_system_sources += Split(''' kern/tru64/dump_mbuf.cc @@ -316,9 +290,12 @@ env.Append(CPPPATH=Dir('.')) # Add a flag defining what THE_ISA should be for all compilation env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) -arch_sources = SConscript('arch/SConscript', exports = 'env') +arch_sources = SConscript(os.path.join('arch', 'SConscript'), exports = 'env') + +cpu_sources = SConscript(os.path.join('cpu', 'SConscript'), exports = 'env') -cpu_sources = SConscript('cpu/SConscript', exports = 'env') +dev_sources = SConscript(os.path.join('dev', 'SConscript'), exports = 'env') +full_system_sources += dev_sources # This is outside of cpu/SConscript since the source directory isn't # underneath 'cpu'. diff --git a/src/arch/SConscript b/src/arch/SConscript index dda1dea53..2ef3d5ee0 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -49,10 +49,12 @@ sources = [] isa_switch_hdrs = Split(''' arguments.hh faults.hh + interrupts.hh isa_traits.hh locked_mem.hh process.hh regfile.hh + remote_gdb.hh stacktrace.hh syscallreturn.hh tlb.hh diff --git a/src/arch/alpha/SConscript b/src/arch/alpha/SConscript index 9a5680649..2d733d73b 100644 --- a/src/arch/alpha/SConscript +++ b/src/arch/alpha/SConscript @@ -60,6 +60,7 @@ full_system_sources = Split(''' osfpal.cc stacktrace.cc vtophys.cc + remote_gdb.cc system.cc freebsd/system.cc linux/system.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 314b445e0..6f8f255b4 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -33,7 +33,7 @@ #include "arch/alpha/isa_traits.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" @@ -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)); 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/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/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index be6f574a9..7014d4c22 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -795,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/base/kgdb.h b/src/arch/alpha/kgdb.h index 104244d0b..104244d0b 100644 --- a/src/base/kgdb.h +++ b/src/arch/alpha/kgdb.h diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc new file mode 100644 index 000000000..96c7ea6e2 --- /dev/null +++ b/src/arch/alpha/remote_gdb.cc @@ -0,0 +1,424 @@ +/* + * 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/alpha/remote_gdb.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 AlphaISA; + +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::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/alpha/remote_gdb.hh b/src/arch/alpha/remote_gdb.hh new file mode 100644 index 000000000..1dd4ada38 --- /dev/null +++ b/src/arch/alpha/remote_gdb.hh @@ -0,0 +1,130 @@ +/* + * 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 + { + 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); + + 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/alpha/system.cc b/src/arch/alpha/system.cc index 5597eaedc..710f6ef46 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -31,8 +31,8 @@ #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" 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); } diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index e4efa31e3..01166d46f 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -123,7 +123,6 @@ #include "arch/vtophys.hh" #include "base/intmath.hh" -#include "base/kgdb.h" #include "base/remote_gdb.hh" #include "base/socket.hh" #include "base/trace.hh" @@ -138,18 +137,18 @@ using namespace std; using namespace TheISA; #ifndef NDEBUG -vector<RemoteGDB *> debuggers; -int current_debugger = -1; +vector<BaseRemoteGDB *> debuggers; void debugger() { + static int current_debugger = -1; if (current_debugger >= 0 && current_debugger < debuggers.size()) { - RemoteGDB *gdb = debuggers[current_debugger]; + BaseRemoteGDB *gdb = debuggers[current_debugger]; if (!gdb->isattached()) gdb->listener->accept(); if (gdb->isattached()) - gdb->trap(ALPHA_KENTRY_IF); + gdb->trap(SIGILL); } } #endif @@ -169,7 +168,7 @@ GDBListener::Event::process(int revent) listener->accept(); } -GDBListener::GDBListener(RemoteGDB *g, int p) +GDBListener::GDBListener(BaseRemoteGDB *g, int p) : event(NULL), gdb(g), port(p) { assert(!gdb->listener); @@ -229,55 +228,46 @@ GDBListener::accept() } } -/////////////////////////////////////////////////////////// -// -// -// -int digit2i(char); -char i2digit(int); -void mem2hex(void *, const void *, int); -const char *hex2mem(void *, const char *, int); -Addr hex2i(const char **); - -RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e) +BaseRemoteGDB::Event::Event(BaseRemoteGDB *g, int fd, int e) : PollEvent(fd, e), gdb(g) {} void -RemoteGDB::Event::process(int revent) +BaseRemoteGDB::Event::process(int revent) { if (revent & POLLIN) - gdb->trap(ALPHA_KENTRY_IF); + gdb->trap(SIGILL); else if (revent & POLLNVAL) gdb->detach(); } -RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) +BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, size_t cacheSize) : event(NULL), listener(NULL), number(-1), fd(-1), active(false), attached(false), - system(_system), pmem(_system->physmem), context(c) + system(_system), pmem(_system->physmem), context(c), + gdbregs(cacheSize) { - memset(gdbregs, 0, sizeof(gdbregs)); + memset(gdbregs.regs, 0, gdbregs.size); } -RemoteGDB::~RemoteGDB() +BaseRemoteGDB::~BaseRemoteGDB() { if (event) delete event; } string -RemoteGDB::name() +BaseRemoteGDB::name() { return system->name() + ".remote_gdb"; } bool -RemoteGDB::isattached() +BaseRemoteGDB::isattached() { return attached; } void -RemoteGDB::attach(int f) +BaseRemoteGDB::attach(int f) { fd = f; @@ -289,7 +279,7 @@ RemoteGDB::attach(int f) } void -RemoteGDB::detach() +BaseRemoteGDB::detach() { attached = false; close(fd); @@ -300,250 +290,50 @@ RemoteGDB::detach() } const char * -gdb_command(char cmd) +BaseRemoteGDB::gdb_command(char cmd) { switch (cmd) { - case KGDB_SIGNAL: return "KGDB_SIGNAL"; - case KGDB_SET_BAUD: return "KGDB_SET_BAUD"; - case KGDB_SET_BREAK: return "KGDB_SET_BREAK"; - case KGDB_CONT: return "KGDB_CONT"; - case KGDB_ASYNC_CONT: return "KGDB_ASYNC_CONT"; - case KGDB_DEBUG: return "KGDB_DEBUG"; - case KGDB_DETACH: return "KGDB_DETACH"; - case KGDB_REG_R: return "KGDB_REG_R"; - case KGDB_REG_W: return "KGDB_REG_W"; - case KGDB_SET_THREAD: return "KGDB_SET_THREAD"; - case KGDB_CYCLE_STEP: return "KGDB_CYCLE_STEP"; - case KGDB_SIG_CYCLE_STEP: return "KGDB_SIG_CYCLE_STEP"; - case KGDB_KILL: return "KGDB_KILL"; - case KGDB_MEM_W: return "KGDB_MEM_W"; - case KGDB_MEM_R: return "KGDB_MEM_R"; - case KGDB_SET_REG: return "KGDB_SET_REG"; - case KGDB_READ_REG: return "KGDB_READ_REG"; - case KGDB_QUERY_VAR: return "KGDB_QUERY_VAR"; - case KGDB_SET_VAR: return "KGDB_SET_VAR"; - case KGDB_RESET: return "KGDB_RESET"; - case KGDB_STEP: return "KGDB_STEP"; - case KGDB_ASYNC_STEP: return "KGDB_ASYNC_STEP"; - case KGDB_THREAD_ALIVE: return "KGDB_THREAD_ALIVE"; - case KGDB_TARGET_EXIT: return "KGDB_TARGET_EXIT"; - case KGDB_BINARY_DLOAD: return "KGDB_BINARY_DLOAD"; - case KGDB_CLR_HW_BKPT: return "KGDB_CLR_HW_BKPT"; - case KGDB_SET_HW_BKPT: return "KGDB_SET_HW_BKPT"; - case KGDB_START: return "KGDB_START"; - case KGDB_END: return "KGDB_END"; - case KGDB_GOODP: return "KGDB_GOODP"; - case KGDB_BADP: return "KGDB_BADP"; + case GDBSignal: return "KGDB_SIGNAL"; + case GDBSetBaud: return "KGDB_SET_BAUD"; + case GDBSetBreak: return "KGDB_SET_BREAK"; + case GDBCont: return "KGDB_CONT"; + case GDBAsyncCont: return "KGDB_ASYNC_CONT"; + case GDBDebug: return "KGDB_DEBUG"; + case GDBDetach: return "KGDB_DETACH"; + case GDBRegR: return "KGDB_REG_R"; + case GDBRegW: return "KGDB_REG_W"; + case GDBSetThread: return "KGDB_SET_THREAD"; + case GDBCycleStep: return "KGDB_CYCLE_STEP"; + case GDBSigCycleStep: return "KGDB_SIG_CYCLE_STEP"; + case GDBKill: return "KGDB_KILL"; + case GDBMemW: return "KGDB_MEM_W"; + case GDBMemR: return "KGDB_MEM_R"; + case GDBSetReg: return "KGDB_SET_REG"; + case GDBReadReg: return "KGDB_READ_REG"; + case GDBQueryVar: return "KGDB_QUERY_VAR"; + case GDBSetVar: return "KGDB_SET_VAR"; + case GDBReset: return "KGDB_RESET"; + case GDBStep: return "KGDB_STEP"; + case GDBAsyncStep: return "KGDB_ASYNC_STEP"; + case GDBThreadAlive: return "KGDB_THREAD_ALIVE"; + case GDBTargetExit: return "KGDB_TARGET_EXIT"; + case GDBBinaryDload: return "KGDB_BINARY_DLOAD"; + case GDBClrHwBkpt: return "KGDB_CLR_HW_BKPT"; + case GDBSetHwBkpt: return "KGDB_SET_HW_BKPT"; + case GDBStart: return "KGDB_START"; + case GDBEnd: return "KGDB_END"; + case GDBGoodP: return "KGDB_GOODP"; + case GDBBadP: return "KGDB_BADP"; default: return "KGDB_UNKNOWN"; } } -/////////////////////////////////////////////////////////// -// 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, 0, sizeof(gdbregs)); - - gdbregs[KGDB_REG_PC] = context->readPC(); - - // @todo: Currently this is very Alpha specific. - if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) { - for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { - gdbregs[i] = context->readIntReg(AlphaISA::reg_redir[i]); - } - } else { - for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { - gdbregs[i] = context->readIntReg(i); - } - } - -#ifdef KGDB_FP_REGS - for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { - gdbregs[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[KGDB_REG_PC])) { - for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { - context->setIntReg(AlphaISA::reg_redir[i], gdbregs[i]); - } - } else { - for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { - context->setIntReg(i, gdbregs[i]); - } - } - -#ifdef KGDB_FP_REGS - for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { - context->setFloatRegBits(i, gdbregs[i + KGDB_REG_F0]); - } -#endif - context->setPC(gdbregs[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); -} - ///////////////////////// // // uint8_t -RemoteGDB::getbyte() +BaseRemoteGDB::getbyte() { uint8_t b; ::read(fd, &b, 1); @@ -551,14 +341,14 @@ RemoteGDB::getbyte() } void -RemoteGDB::putbyte(uint8_t b) +BaseRemoteGDB::putbyte(uint8_t b) { ::write(fd, &b, 1); } // Send a packet to gdb void -RemoteGDB::send(const char *bp) +BaseRemoteGDB::send(const char *bp) { const char *p; uint8_t csum, c; @@ -567,20 +357,26 @@ RemoteGDB::send(const char *bp) do { p = bp; - putbyte(KGDB_START); + //Start sending a packet + putbyte(GDBStart); + //Send the contents, and also keep a check sum. for (csum = 0; (c = *p); p++) { putbyte(c); csum += c; } - putbyte(KGDB_END); + //Send the ending character. + putbyte(GDBEnd); + //Sent the checksum. putbyte(i2digit(csum >> 4)); putbyte(i2digit(csum)); - } while ((c = getbyte() & 0x7f) == KGDB_BADP); + //Try transmitting over and over again until the other end doesn't send an + //error back. + } while ((c = getbyte() & 0x7f) == GDBBadP); } // Receive a packet from gdb int -RemoteGDB::recv(char *bp, int maxlen) +BaseRemoteGDB::recv(char *bp, int maxlen) { char *p; int c, csum; @@ -589,28 +385,37 @@ RemoteGDB::recv(char *bp, int maxlen) do { p = bp; csum = len = 0; - while ((c = getbyte()) != KGDB_START) + //Find the beginning of a packet + while ((c = getbyte()) != GDBStart) ; - while ((c = getbyte()) != KGDB_END && len < maxlen) { + //Read until you find the end of the data in the packet, and keep + //track of the check sum. + while ((c = getbyte()) != GDBEnd && len < maxlen) { c &= 0x7f; csum += c; *p++ = c; len++; } + + //Mask the check sum, and terminate the command string. csum &= 0xff; *p = '\0'; + //If the command was too long, report an error. if (len >= maxlen) { - putbyte(KGDB_BADP); + putbyte(GDBBadP); continue; } + //Bring in the checksum. If the check sum matches, csum will be 0. csum -= digit2i(getbyte()) * 16; csum -= digit2i(getbyte()); + //If the check sum was correct if (csum == 0) { - putbyte(KGDB_GOODP); + //Report that the packet was received correctly + putbyte(GDBGoodP); // Sequence present? if (bp[2] == ':') { putbyte(bp[0]); @@ -620,7 +425,8 @@ RemoteGDB::recv(char *bp, int maxlen) } break; } - putbyte(KGDB_BADP); + //Otherwise, report that there was a mistake. + putbyte(GDBBadP); } while (1); DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp); @@ -630,7 +436,7 @@ RemoteGDB::recv(char *bp, int maxlen) // Read bytes from kernel address space for debugger. bool -RemoteGDB::read(Addr vaddr, size_t size, char *data) +BaseRemoteGDB::read(Addr vaddr, size_t size, char *data) { static Addr lastaddr = 0; static size_t lastsize = 0; @@ -662,7 +468,7 @@ RemoteGDB::read(Addr vaddr, size_t size, char *data) // Write bytes to kernel address space for debugger. bool -RemoteGDB::write(Addr vaddr, size_t size, const char *data) +BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data) { static Addr lastaddr = 0; static size_t lastsize = 0; @@ -685,21 +491,15 @@ RemoteGDB::write(Addr vaddr, size_t size, const char *data) vp->writeBlob(vaddr, (uint8_t*)data, size); context->delVirtPort(vp); -#ifdef IMB - alpha_pal_imb(); -#endif - return true; } - -PCEventQueue *RemoteGDB::getPcEventQueue() +PCEventQueue *BaseRemoteGDB::getPcEventQueue() { return &system->pcEventQueue; } - -RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc) +BaseRemoteGDB::HardBreakpoint::HardBreakpoint(BaseRemoteGDB *_gdb, Addr pc) : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc), gdb(_gdb), refcount(0) { @@ -707,25 +507,25 @@ RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc) } void -RemoteGDB::HardBreakpoint::process(ThreadContext *tc) +BaseRemoteGDB::HardBreakpoint::process(ThreadContext *tc) { DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc()); if (tc == gdb->context) - gdb->trap(ALPHA_KENTRY_INT); + gdb->trap(SIGTRAP); } bool -RemoteGDB::insertSoftBreak(Addr addr, size_t len) +BaseRemoteGDB::insertSoftBreak(Addr addr, size_t len) { - if (len != sizeof(MachInst)) + if (len != sizeof(TheISA::MachInst)) panic("invalid length\n"); return insertHardBreak(addr, len); } bool -RemoteGDB::removeSoftBreak(Addr addr, size_t len) +BaseRemoteGDB::removeSoftBreak(Addr addr, size_t len) { if (len != sizeof(MachInst)) panic("invalid length\n"); @@ -734,7 +534,7 @@ RemoteGDB::removeSoftBreak(Addr addr, size_t len) } bool -RemoteGDB::insertHardBreak(Addr addr, size_t len) +BaseRemoteGDB::insertHardBreak(Addr addr, size_t len) { if (len != sizeof(MachInst)) panic("invalid length\n"); @@ -751,7 +551,7 @@ RemoteGDB::insertHardBreak(Addr addr, size_t len) } bool -RemoteGDB::removeHardBreak(Addr addr, size_t len) +BaseRemoteGDB::removeHardBreak(Addr addr, size_t len) { if (len != sizeof(MachInst)) panic("invalid length\n"); @@ -772,7 +572,7 @@ RemoteGDB::removeHardBreak(Addr addr, size_t len) } const char * -break_type(char c) +BaseRemoteGDB::break_type(char c) { switch(c) { case '0': return "software breakpoint"; @@ -790,12 +590,12 @@ break_type(char c) // makes sense to use POSIX errno values, because that is what the // gdb/remote.c functions want to return. bool -RemoteGDB::trap(int type) +BaseRemoteGDB::trap(int type) { uint64_t val; size_t datalen, len; - char data[KGDB_BUFLEN + 1]; - char buffer[sizeof(gdbregs) * 2 + 256]; + char data[GDBPacketBufLen + 1]; + char buffer[gdbregs.size * 2 + 256]; const char *p; char command, subcmd; string var; @@ -823,7 +623,7 @@ RemoteGDB::trap(int type) active = true; else // Tell remote host that an exception has occurred. - snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type)); + snprintf((char *)buffer, sizeof(buffer), "S%02x", type); send(buffer); // Stick frame regs into our reg cache. @@ -837,24 +637,25 @@ RemoteGDB::trap(int type) p = data + 1; switch (command) { - case KGDB_SIGNAL: + case GDBSignal: // if this command came from a running gdb, answer it -- // the other guy has no way of knowing if we're in or out // of this loop when he issues a "remote-signal". - snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type)); + snprintf((char *)buffer, sizeof(buffer), + "S%02x", type); send(buffer); continue; - case KGDB_REG_R: - if (2 * sizeof(gdbregs) > sizeof(buffer)) + case GDBRegR: + if (2 * gdbregs.size > sizeof(buffer)) panic("buffer too small"); - mem2hex(buffer, gdbregs, sizeof(gdbregs)); + mem2hex(buffer, gdbregs.regs, gdbregs.size); send(buffer); continue; - case KGDB_REG_W: - p = hex2mem(gdbregs, p, sizeof(gdbregs)); + case GDBRegW: + p = hex2mem(gdbregs.regs, p, gdbregs.size); if (p == NULL || *p != '\0') send("E01"); else { @@ -864,7 +665,7 @@ RemoteGDB::trap(int type) continue; #if 0 - case KGDB_SET_REG: + case GDBSetReg: val = hex2i(&p); if (*p++ != '=') { send("E01"); @@ -875,14 +676,14 @@ RemoteGDB::trap(int type) continue; } - gdbregs[val] = hex2i(&p); + gdbregs.regs[val] = hex2i(&p); setregs(); send("OK"); continue; #endif - case KGDB_MEM_R: + case GDBMemR: val = hex2i(&p); if (*p++ != ',') { send("E02"); @@ -914,7 +715,7 @@ RemoteGDB::trap(int type) } continue; - case KGDB_MEM_W: + case GDBMemW: val = hex2i(&p); if (*p++ != ',') { send("E06"); @@ -944,7 +745,7 @@ RemoteGDB::trap(int type) send("E0B"); continue; - case KGDB_SET_THREAD: + case GDBSetThread: subcmd = *p++; val = hex2i(&p); if (val == 0) @@ -953,14 +754,14 @@ RemoteGDB::trap(int type) send("E01"); continue; - case KGDB_DETACH: - case KGDB_KILL: + case GDBDetach: + case GDBKill: active = false; clearSingleStep(); detach(); goto out; - case KGDB_ASYNC_CONT: + case GDBAsyncCont: subcmd = hex2i(&p); if (*p++ == ';') { val = hex2i(&p); @@ -970,7 +771,7 @@ RemoteGDB::trap(int type) clearSingleStep(); goto out; - case KGDB_CONT: + case GDBCont: if (p - data < datalen) { val = hex2i(&p); context->setPC(val); @@ -979,7 +780,7 @@ RemoteGDB::trap(int type) clearSingleStep(); goto out; - case KGDB_ASYNC_STEP: + case GDBAsyncStep: subcmd = hex2i(&p); if (*p++ == ';') { val = hex2i(&p); @@ -989,7 +790,7 @@ RemoteGDB::trap(int type) setSingleStep(); goto out; - case KGDB_STEP: + case GDBStep: if (p - data < datalen) { val = hex2i(&p); context->setPC(val); @@ -998,7 +799,7 @@ RemoteGDB::trap(int type) setSingleStep(); goto out; - case KGDB_CLR_HW_BKPT: + case GDBClrHwBkpt: subcmd = *p++; if (*p++ != ',') send("E0D"); val = hex2i(&p); @@ -1030,7 +831,7 @@ RemoteGDB::trap(int type) send(ret ? "OK" : "E0C"); continue; - case KGDB_SET_HW_BKPT: + case GDBSetHwBkpt: subcmd = *p++; if (*p++ != ',') send("E0D"); val = hex2i(&p); @@ -1062,7 +863,7 @@ RemoteGDB::trap(int type) send(ret ? "OK" : "E0C"); continue; - case KGDB_QUERY_VAR: + case GDBQueryVar: var = string(p, datalen - 1); if (var == "C") send("QC0"); @@ -1070,17 +871,17 @@ RemoteGDB::trap(int type) send(""); continue; - case KGDB_SET_BAUD: - case KGDB_SET_BREAK: - case KGDB_DEBUG: - case KGDB_CYCLE_STEP: - case KGDB_SIG_CYCLE_STEP: - case KGDB_READ_REG: - case KGDB_SET_VAR: - case KGDB_RESET: - case KGDB_THREAD_ALIVE: - case KGDB_TARGET_EXIT: - case KGDB_BINARY_DLOAD: + case GDBSetBaud: + case GDBSetBreak: + case GDBDebug: + case GDBCycleStep: + case GDBSigCycleStep: + case GDBReadReg: + case GDBSetVar: + case GDBReset: + case GDBThreadAlive: + case GDBTargetExit: + case GDBBinaryDload: // Unsupported command DPRINTF(GDBMisc, "Unsupported command: %s\n", gdb_command(command)); @@ -1106,7 +907,7 @@ RemoteGDB::trap(int type) // Convert a hex digit into an integer. // This returns -1 if the argument passed is no valid hex digit. int -digit2i(char c) +BaseRemoteGDB::digit2i(char c) { if (c >= '0' && c <= '9') return (c - '0'); @@ -1121,14 +922,14 @@ digit2i(char c) // Convert the low 4 bits of an integer into an hex digit. char -i2digit(int n) +BaseRemoteGDB::i2digit(int n) { return ("0123456789abcdef"[n & 0x0f]); } // Convert a byte array into an hex string. void -mem2hex(void *vdst, const void *vsrc, int len) +BaseRemoteGDB::mem2hex(void *vdst, const void *vsrc, int len) { char *dst = (char *)vdst; const char *src = (const char *)vsrc; @@ -1145,7 +946,7 @@ mem2hex(void *vdst, const void *vsrc, int len) // hex digit. If the string ends in the middle of a byte, NULL is // returned. const char * -hex2mem(void *vdst, const char *src, int maxlen) +BaseRemoteGDB::hex2mem(void *vdst, const char *src, int maxlen) { char *dst = (char *)vdst; int msb, lsb; @@ -1166,7 +967,7 @@ hex2mem(void *vdst, const char *src, int maxlen) // This returns a pointer to the character following the last valid // hex digit. Addr -hex2i(const char **srcp) +BaseRemoteGDB::hex2i(const char **srcp) { const char *src = *srcp; Addr r = 0; diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh index 8c3ce7572..65e4313eb 100644 --- a/src/base/remote_gdb.hh +++ b/src/base/remote_gdb.hh @@ -34,7 +34,6 @@ #include <map> #include "arch/types.hh" -#include "base/kgdb.h" #include "cpu/pc_event.hh" #include "base/pollevent.hh" #include "base/socket.hh" @@ -44,22 +43,72 @@ class ThreadContext; class PhysicalMemory; class GDBListener; -class RemoteGDB + +enum GDBCommands +{ + GDBSignal = '?', // last signal + GDBSetBaud = 'b', // set baud (depracated) + GDBSetBreak = 'B', // set breakpoint (depracated) + GDBCont = 'c', // resume + GDBAsyncCont = 'C', // continue with signal + GDBDebug = 'd', // toggle debug flags (deprecated) + GDBDetach = 'D', // detach remote gdb + GDBRegR = 'g', // read general registers + GDBRegW = 'G', // write general registers + GDBSetThread = 'H', // set thread + GDBCycleStep = 'i', // step a single cycle + GDBSigCycleStep = 'I', // signal then cycle step + GDBKill = 'k', // kill program + GDBMemR = 'm', // read memory + GDBMemW = 'M', // write memory + GDBReadReg = 'p', // read register + GDBSetReg = 'P', // write register + GDBQueryVar = 'q', // query variable + GDBSetVar = 'Q', // set variable + GDBReset = 'r', // reset system. (Deprecated) + GDBStep = 's', // step + GDBAsyncStep = 'S', // signal and step + GDBThreadAlive = 'T', // find out if the thread is alive + GDBTargetExit = 'W', // target exited + GDBBinaryDload = 'X', // write memory + GDBClrHwBkpt = 'z', // remove breakpoint or watchpoint + GDBSetHwBkpt = 'Z' // insert breakpoint or watchpoint +}; + +const char GDBStart = '$'; +const char GDBEnd = '#'; +const char GDBGoodP = '+'; +const char GDBBadP = '-'; + +const int GDBPacketBufLen = 1024; + +class BaseRemoteGDB { - protected: - typedef TheISA::MachInst MachInst; private: friend void debugger(); friend class GDBListener; + //Helper functions + protected: + int digit2i(char); + char i2digit(int); + Addr hex2i(const char **); + //Address formats, break types, and gdb commands may change + //between architectures, so they're defined as virtual + //functions. + virtual void mem2hex(void *, const void *, int); + virtual const char * hex2mem(void *, const char *, int); + virtual const char * break_type(char c); + virtual const char * gdb_command(char cmd); + protected: class Event : public PollEvent { protected: - RemoteGDB *gdb; + BaseRemoteGDB *gdb; public: - Event(RemoteGDB *g, int fd, int e); + Event(BaseRemoteGDB *g, int fd, int e); void process(int revent); }; @@ -69,8 +118,8 @@ class RemoteGDB int number; protected: + //The socket commands come in through int fd; - uint64_t gdbregs[KGDB_NUMREGS]; protected: #ifdef notyet @@ -84,6 +133,23 @@ class RemoteGDB ThreadContext *context; protected: + class GdbRegCache + { + public: + GdbRegCache(size_t newSize) : regs(new uint64_t[newSize]), size(newSize) + {} + ~GdbRegCache() + { + delete [] regs; + } + + uint64_t * regs; + size_t size; + }; + + GdbRegCache gdbregs; + + protected: uint8_t getbyte(); void putbyte(uint8_t b); @@ -92,15 +158,15 @@ class RemoteGDB protected: // Machine memory - bool read(Addr addr, size_t size, char *data); - bool write(Addr addr, size_t size, const char *data); + virtual bool read(Addr addr, size_t size, char *data); + virtual bool write(Addr addr, size_t size, const char *data); template <class T> T read(Addr addr); template <class T> void write(Addr addr, T data); public: - RemoteGDB(System *system, ThreadContext *context); - ~RemoteGDB(); + BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize); + virtual ~BaseRemoteGDB(); void replaceThreadContext(ThreadContext *tc) { context = tc; } @@ -108,16 +174,15 @@ class RemoteGDB void detach(); bool isattached(); - bool acc(Addr addr, size_t len); - static int signal(int type); + virtual bool acc(Addr addr, size_t len) = 0; bool trap(int type); protected: - void getregs(); - void setregs(); + virtual void getregs() = 0; + virtual void setregs() = 0; - void clearSingleStep(); - void setSingleStep(); + virtual void clearSingleStep() = 0; + virtual void setSingleStep() = 0; PCEventQueue *getPcEventQueue(); @@ -125,13 +190,13 @@ class RemoteGDB class HardBreakpoint : public PCEvent { private: - RemoteGDB *gdb; + BaseRemoteGDB *gdb; public: int refcount; public: - HardBreakpoint(RemoteGDB *_gdb, Addr addr); + HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr); std::string name() { return gdb->name() + ".hwbkpt"; } virtual void process(ThreadContext *tc); @@ -147,27 +212,13 @@ class RemoteGDB 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); - public: std::string name(); }; template <class T> inline T -RemoteGDB::read(Addr addr) +BaseRemoteGDB::read(Addr addr) { T temp; read(addr, sizeof(T), (char *)&temp); @@ -176,7 +227,7 @@ RemoteGDB::read(Addr addr) template <class T> inline void -RemoteGDB::write(Addr addr, T data) +BaseRemoteGDB::write(Addr addr, T data) { write(addr, sizeof(T), (const char *)&data); } class GDBListener @@ -197,11 +248,11 @@ class GDBListener protected: ListenSocket listener; - RemoteGDB *gdb; + BaseRemoteGDB *gdb; int port; public: - GDBListener(RemoteGDB *g, int p); + GDBListener(BaseRemoteGDB *g, int p); ~GDBListener(); void accept(); diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 55ceea8fb..4c243a2e9 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -168,11 +168,6 @@ BaseCPU::BaseCPU(Params *p) p->max_loads_all_threads, *counter); } -#if FULL_SYSTEM - memset(interrupts, 0, sizeof(interrupts)); - intstatus = 0; -#endif - functionTracingEnabled = false; if (p->functionTrace) { functionTraceStream = simout.find(csprintf("ftrace.%s", name())); @@ -334,9 +329,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) } #if FULL_SYSTEM - for (int i = 0; i < TheISA::NumInterruptLevels; ++i) - interrupts[i] = oldCPU->interrupts[i]; - intstatus = oldCPU->intstatus; + interrupts = oldCPU->interrupts; checkInterrupts = oldCPU->checkInterrupts; for (int i = 0; i < threadContexts.size(); ++i) @@ -368,57 +361,33 @@ BaseCPU::ProfileEvent::process() void BaseCPU::post_interrupt(int int_num, int index) { - DPRINTF(Interrupt, "Interrupt %d:%d posted\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"); - checkInterrupts = true; - interrupts[int_num] |= 1 << index; - intstatus |= (ULL(1) << int_num); + interrupts.post(int_num, index); } void BaseCPU::clear_interrupt(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); + interrupts.clear(int_num, index); } void BaseCPU::clear_interrupts() { - DPRINTF(Interrupt, "Interrupts all cleared\n"); - - memset(interrupts, 0, sizeof(interrupts)); - intstatus = 0; + interrupts.clear_all(); } void BaseCPU::serialize(std::ostream &os) { - SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); - SERIALIZE_SCALAR(intstatus); + interrupts.serialize(os); } void BaseCPU::unserialize(Checkpoint *cp, const std::string §ion) { - UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); - UNSERIALIZE_SCALAR(intstatus); + interrupts.unserialize(cp, section); } #endif // FULL_SYSTEM diff --git a/src/cpu/base.hh b/src/cpu/base.hh index df665ed23..9257778ef 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -40,6 +40,10 @@ #include "mem/mem_object.hh" #include "arch/isa_traits.hh" +#if FULL_SYSTEM +#include "arch/interrupts.hh" +#endif + class BranchPred; class CheckerCPU; class ThreadContext; @@ -89,8 +93,9 @@ class BaseCPU : public MemObject #if FULL_SYSTEM protected: - uint64_t interrupts[TheISA::NumInterruptLevels]; - uint64_t intstatus; +// uint64_t interrupts[TheISA::NumInterruptLevels]; +// uint64_t intstatus; + TheISA::Interrupts interrupts; public: virtual void post_interrupt(int int_num, int index); @@ -98,15 +103,8 @@ class BaseCPU : public MemObject virtual void clear_interrupts(); bool checkInterrupts; - bool check_interrupt(int int_num) const { - if (int_num > TheISA::NumInterruptLevels) - panic("int_num out of bounds\n"); - - return interrupts[int_num] != 0; - } - - bool check_interrupts() const { return intstatus != 0; } - uint64_t intr_status() const { return intstatus; } + bool check_interrupts(ThreadContext * tc) const + { return interrupts.check_interrupts(tc); } class ProfileEvent : public Event { diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 454f3892b..9be54529f 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -327,7 +327,6 @@ class CheckerCPU : public BaseCPU #if FULL_SYSTEM Fault hwrei() { return thread->hwrei(); } - bool inPalMode() { return thread->inPalMode(); } void ev5_trap(Fault fault) { fault->invoke(tc); } bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index cd399dd22..b46031167 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -271,9 +271,6 @@ class CheckerThreadContext : public ThreadContext checkerTC->setStCondFailures(sc_failures); actualTC->setStCondFailures(sc_failures); } -#if FULL_SYSTEM - bool inPalMode() { return actualTC->inPalMode(); } -#endif // @todo: Fix this! bool misspeculating() { return actualTC->misspeculating(); } diff --git a/src/cpu/cpuevent.hh b/src/cpu/cpuevent.hh index 9dfae27cf..3339f8252 100644 --- a/src/cpu/cpuevent.hh +++ b/src/cpu/cpuevent.hh @@ -44,7 +44,7 @@ class ThreadContext; * */ class CpuEvent : public Event { - private: + protected: /** type of global list of cpu events. */ typedef std::vector<CpuEvent *> CpuEventList; diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index 01749a2a2..b62550062 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -153,9 +153,6 @@ class AlphaO3CPU : public FullO3CPU<Impl> void post_interrupt(int int_num, int index); /** HW return from error interrupt. */ Fault hwrei(unsigned tid); - /** Returns if a specific PC is a PAL mode PC. */ - bool inPalMode(uint64_t PC) - { return AlphaISA::PcPAL(PC); } bool simPalCheck(int palFunc, unsigned tid); diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh index f5c2170ce..750ccc912 100644 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ b/src/cpu/o3/alpha/cpu_impl.hh @@ -270,7 +270,6 @@ template <class Impl> void AlphaO3CPU<Impl>::processInterrupts() { - using namespace TheISA; // Check for interrupts here. For now can copy the code that // exists within isa_fullsys_traits.hh. Also assume that thread 0 // is the one that handles the interrupts. @@ -279,51 +278,11 @@ AlphaO3CPU<Impl>::processInterrupts() // Check if there are any outstanding interrupts //Handle the interrupts - int ipl = 0; - int summary = 0; - - this->checkInterrupts = false; - - if (this->readMiscReg(IPR_ASTRR, 0)) - panic("asynchronous traps not implemented\n"); - - if (this->readMiscReg(IPR_SIRR, 0)) { - for (int i = INTLEVEL_SOFTWARE_MIN; - i < INTLEVEL_SOFTWARE_MAX; i++) { - if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) { - // See table 4-19 of the 21164 hardware reference - ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; - summary |= (ULL(1) << i); - } - } - } - - uint64_t interrupts = this->intr_status(); + Fault interrupt = this->interrupts.getInterrupt(this->tcBase(0)); - if (interrupts) { - for (int i = INTLEVEL_EXTERNAL_MIN; - i < INTLEVEL_EXTERNAL_MAX; i++) { - if (interrupts & (ULL(1) << i)) { - // See table 4-19 of the 21164 hardware reference - ipl = i; - summary |= (ULL(1) << i); - } - } - } - - if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) { - this->setMiscReg(IPR_ISR, summary, 0); - this->setMiscReg(IPR_INTID, ipl, 0); - // 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 - this->trap(Fault(new InterruptFault), 0); - DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - this->readMiscReg(IPR_IPLR, 0), ipl, summary); + if (interrupt != NoFault) { + this->checkInterrupts = false; + this->trap(interrupt, 0); } } diff --git a/src/cpu/o3/alpha/dyn_inst.hh b/src/cpu/o3/alpha/dyn_inst.hh index e711de510..31df8ff78 100644 --- a/src/cpu/o3/alpha/dyn_inst.hh +++ b/src/cpu/o3/alpha/dyn_inst.hh @@ -126,8 +126,6 @@ class AlphaDynInst : public BaseDynInst<Impl> #if FULL_SYSTEM /** Calls hardware return from error interrupt. */ Fault hwrei(); - /** Checks if system is in PAL mode. */ - bool inPalMode(); /** Traps to handle specified fault. */ void trap(Fault fault); bool simPalCheck(int palFunc); diff --git a/src/cpu/o3/alpha/dyn_inst_impl.hh b/src/cpu/o3/alpha/dyn_inst_impl.hh index f27cd5961..6fc548a85 100644 --- a/src/cpu/o3/alpha/dyn_inst_impl.hh +++ b/src/cpu/o3/alpha/dyn_inst_impl.hh @@ -113,7 +113,7 @@ Fault AlphaDynInst<Impl>::hwrei() { // Can only do a hwrei when in pal mode. - if (!this->cpu->inPalMode(this->readPC())) + if (!(this->readPC() & 0x3)) return new AlphaISA::UnimplementedOpcodeFault; // Set the next PC based on the value of the EXC_ADDR IPR. @@ -128,13 +128,6 @@ AlphaDynInst<Impl>::hwrei() } template <class Impl> -bool -AlphaDynInst<Impl>::inPalMode() -{ - return this->cpu->inPalMode(this->PC); -} - -template <class Impl> void AlphaDynInst<Impl>::trap(Fault fault) { diff --git a/src/cpu/o3/alpha/thread_context.hh b/src/cpu/o3/alpha/thread_context.hh index f0cecee35..bcecb7087 100644 --- a/src/cpu/o3/alpha/thread_context.hh +++ b/src/cpu/o3/alpha/thread_context.hh @@ -47,11 +47,6 @@ class AlphaTC : public O3ThreadContext<Impl> { return this->thread->quiesceEvent; } - - /** Returns if the thread is currently in PAL mode, based on - * the PC's value. */ - virtual bool inPalMode() - { return TheISA::PcPAL(this->cpu->readPC(this->thread->readTid())); } #endif virtual uint64_t readNextNPC() diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index ecf6ed632..bd5c4f9ce 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -638,8 +638,7 @@ DefaultCommit<Impl>::commit() // and no other traps or external squashes are currently pending. // @todo: Allow other threads to handle interrupts. if (cpu->checkInterrupts && - cpu->check_interrupts() && - !cpu->inPalMode(readPC()) && + cpu->check_interrupts(cpu->tcBase(0)) && !trapSquash[0] && !tcSquash[0]) { // Tell fetch that there is an interrupt pending. This will diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 31f3b96d6..5ef6e27ea 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -45,7 +45,6 @@ #if FULL_SYSTEM #include "arch/tlb.hh" #include "arch/vtophys.hh" -#include "base/remote_gdb.hh" #include "sim/system.hh" #endif // FULL_SYSTEM @@ -559,14 +558,9 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid { Fault fault = NoFault; -#if FULL_SYSTEM - // Flag to say whether or not address is physical addr. - unsigned flags = cpu->inPalMode(fetch_PC) ? PHYSICAL : 0; -#else - unsigned flags = 0; -#endif // FULL_SYSTEM - - if (cacheBlocked || isSwitchedOut() || (interruptPending && flags == 0)) { + //AlphaDep + if (cacheBlocked || isSwitchedOut() || + (interruptPending && (fetch_PC & 0x3))) { // Hold off fetch from getting new instructions when: // Cache is blocked, or // while an interrupt is pending and we're not in PAL mode, or @@ -585,7 +579,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid // Setup the memReq to do a read of the first instruction's address. // Set the appropriate read size and flags as well. // Build request here. - RequestPtr mem_req = new Request(tid, fetch_PC, cacheBlkSize, flags, + RequestPtr mem_req = new Request(tid, fetch_PC, cacheBlkSize, 0, fetch_PC, cpu->readCpuId(), tid); memReq[tid] = mem_req; diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 828c2b4ca..b3d3531e9 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -239,10 +239,6 @@ class OzoneCPU : public BaseCPU void setStCondFailures(unsigned sc_failures) { thread->storeCondFailures = sc_failures; } -#if FULL_SYSTEM - bool inPalMode() { return cpu->inPalMode(); } -#endif - bool misspeculating() { return false; } #if !FULL_SYSTEM @@ -584,8 +580,6 @@ class OzoneCPU : public BaseCPU #if FULL_SYSTEM Fault hwrei(); - bool inPalMode() { return AlphaISA::PcPAL(thread.PC); } - bool inPalMode(Addr pc) { return AlphaISA::PcPAL(pc); } bool simPalCheck(int palFunc); void processInterrupts(); #else diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index 532317b08..9445a5309 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -238,7 +238,6 @@ class OzoneDynInst : public BaseDynInst<Impl> #if FULL_SYSTEM Fault hwrei(); - bool inPalMode(); void trap(Fault fault); bool simPalCheck(int palFunc); #else diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index 68736ae61..426841536 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -249,7 +249,7 @@ template <class Impl> Fault OzoneDynInst<Impl>::hwrei() { - if (!this->cpu->inPalMode(this->readPC())) + if (!(this->readPC() & 0x3)) return new AlphaISA::UnimplementedOpcodeFault; this->setNextPC(this->thread->readMiscReg(AlphaISA::IPR_EXC_ADDR)); @@ -261,13 +261,6 @@ OzoneDynInst<Impl>::hwrei() } template <class Impl> -bool -OzoneDynInst<Impl>::inPalMode() -{ - return this->cpu->inPalMode(); -} - -template <class Impl> void OzoneDynInst<Impl>::trap(Fault fault) { diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 6d02c58cb..73ca6afbe 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -462,15 +462,10 @@ Fault FrontEnd<Impl>::fetchCacheLine() { // Read a cache line, based on the current PC. -#if FULL_SYSTEM - // Flag to say whether or not address is physical addr. - unsigned flags = cpu->inPalMode(PC) ? PHYSICAL : 0; -#else - unsigned flags = 0; -#endif // FULL_SYSTEM Fault fault = NoFault; - if (interruptPending && flags == 0) { + //AlphaDep + if (interruptPending && (PC & 0x3)) { return fault; } diff --git a/src/cpu/ozone/inorder_back_end_impl.hh b/src/cpu/ozone/inorder_back_end_impl.hh index 8aef9c074..87bf0a7a2 100644 --- a/src/cpu/ozone/inorder_back_end_impl.hh +++ b/src/cpu/ozone/inorder_back_end_impl.hh @@ -152,11 +152,11 @@ InorderBackEnd<Impl>::tick() #if FULL_SYSTEM if (interruptBlocked || (cpu->checkInterrupts && - cpu->check_interrupts() && - !cpu->inPalMode())) { + cpu->check_interrupts(tc))) { if (!robEmpty()) { interruptBlocked = true; - } else if (robEmpty() && cpu->inPalMode()) { + //AlphaDep + } else if (robEmpty() && (PC & 0x3)) { // Will need to let the front end continue a bit until // we're out of pal mode. Hopefully we never get into an // infinite loop... diff --git a/src/cpu/ozone/lw_back_end_impl.hh b/src/cpu/ozone/lw_back_end_impl.hh index c39b9e08b..a181c93f4 100644 --- a/src/cpu/ozone/lw_back_end_impl.hh +++ b/src/cpu/ozone/lw_back_end_impl.hh @@ -526,8 +526,7 @@ void LWBackEnd<Impl>::checkInterrupts() { if (cpu->checkInterrupts && - cpu->check_interrupts() && - !cpu->inPalMode(thread->readPC()) && + cpu->check_interrupts(tc) && !trapSquash && !tcSquash) { frontEnd->interruptPending = true; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 6a2c0bbe9..e91569db2 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -311,43 +311,12 @@ void BaseSimpleCPU::checkForInterrupts() { #if FULL_SYSTEM - if (checkInterrupts && check_interrupts() && !thread->inPalMode()) { - int ipl = 0; - int summary = 0; - checkInterrupts = false; - - if (thread->readMiscReg(IPR_SIRR)) { - for (int i = INTLEVEL_SOFTWARE_MIN; - i < INTLEVEL_SOFTWARE_MAX; i++) { - if (thread->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 = thread->cpu->intr_status(); - 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 (thread->readMiscReg(IPR_ASTRR)) - panic("asynchronous traps not implemented\n"); - - if (ipl && ipl > thread->readMiscReg(IPR_IPLR)) { - thread->setMiscReg(IPR_ISR, summary); - thread->setMiscReg(IPR_INTID, ipl); - - Fault(new InterruptFault)->invoke(tc); + if (checkInterrupts && check_interrupts(tc)) { + Fault interrupt = interrupts.getInterrupt(tc); - DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - thread->readMiscReg(IPR_IPLR), ipl, summary); + if (interrupt != NoFault) { + checkInterrupts = false; + interrupt->invoke(tc); } } #endif @@ -402,6 +371,10 @@ BaseSimpleCPU::preExecute() StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->readPC())); #elif THE_ISA == SPARC_ISA StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC())); +#elif THE_ISA == MIPS_ISA + //Mips doesn't do anything in it's MakeExtMI function right now, + //so it won't be called. + StaticInstPtr instPtr = StaticInst::decode(inst); #endif if (instPtr->isMacroOp()) { curMacroStaticInst = instPtr; diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index d13be2877..efb884325 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -302,7 +302,6 @@ class BaseSimpleCPU : public BaseCPU #if FULL_SYSTEM Fault hwrei() { return thread->hwrei(); } - bool inPalMode() { return thread->inPalMode(); } void ev5_trap(Fault fault) { fault->invoke(tc); } bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 9a575f06b..600588295 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -440,10 +440,6 @@ class SimpleThread : public ThreadState void setStCondFailures(unsigned sc_failures) { storeCondFailures = sc_failures; } -#if FULL_SYSTEM - bool inPalMode() { return AlphaISA::PcPAL(regs.readPC()); } -#endif - #if !FULL_SYSTEM TheISA::IntReg getSyscallArg(int i) { diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index dfc6fbc2a..82d75b161 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -236,10 +236,6 @@ class ThreadContext virtual void setStCondFailures(unsigned sc_failures) = 0; -#if FULL_SYSTEM - virtual bool inPalMode() = 0; -#endif - // Only really makes sense for old CPU model. Still could be useful though. virtual bool misspeculating() = 0; @@ -424,9 +420,6 @@ class ProxyThreadContext : public ThreadContext void setStCondFailures(unsigned sc_failures) { actualTC->setStCondFailures(sc_failures); } -#if FULL_SYSTEM - bool inPalMode() { return actualTC->inPalMode(); } -#endif // @todo: Fix this! bool misspeculating() { return actualTC->misspeculating(); } diff --git a/src/dev/SConscript b/src/dev/SConscript new file mode 100644 index 000000000..75fca324a --- /dev/null +++ b/src/dev/SConscript @@ -0,0 +1,80 @@ +# -*- mode:python -*- + +# 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 +# Gabe Black + +import os.path, sys + +# Import build environment variable from SConstruct. +Import('env') + +# Right now there are no source files immediately in this directory +sources = [] + +# +# Now include other ISA-specific sources from the ISA subdirectories. +# + +isa = env['TARGET_ISA'] # someday this may be a list of ISAs + +# +# These source files can be used by any architecture +# + +sources += Split(''' + baddev.cc + disk_image.cc + etherbus.cc + etherdump.cc + etherint.cc + etherlink.cc + etherpkt.cc + ethertap.cc + ide_ctrl.cc + ide_disk.cc + io_device.cc + isa_fake.cc + ns_gige.cc + pciconfigall.cc + pcidev.cc + pcifake.cc + pktfifo.cc + platform.cc + simconsole.cc + simple_disk.cc + ''') + +# Let the target architecture define what additional sources it needs +sources += SConscript(os.path.join(isa, 'SConscript'), exports = 'env') + +# Convert file names to SCons File objects. This takes care of the +# path relative to the top of the directory tree. +sources = [File(s) for s in sources] + +Return('sources') diff --git a/src/dev/alpha/SConscript b/src/dev/alpha/SConscript new file mode 100644 index 000000000..304cd9ca9 --- /dev/null +++ b/src/dev/alpha/SConscript @@ -0,0 +1,70 @@ +# -*- mode:python -*- + +# 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 +# Gabe Black + +import os.path, sys + +# Import build environment variable from SConstruct. +Import('env') + +sources = Split(''' + console.cc + tsunami.cc + tsunami_cchip.cc + tsunami_io.cc + tsunami_fake.cc + tsunami_pchip.cc + ''') +# baddev.cc +# disk_image.cc +# etherbus.cc +# etherdump.cc +# etherint.cc +# etherlink.cc +# etherpkt.cc +# ethertap.cc +# ide_ctrl.cc +# ide_disk.cc +# io_device.cc +# isa_fake.cc +# ns_gige.cc +# pciconfigall.cc +# pcidev.cc +# pcifake.cc +# pktfifo.cc +# platform.cc +# simconsole.cc +# simple_disk.cc + +# Convert file names to SCons File objects. This takes care of the +# path relative to the top of the directory tree. +sources = [File(s) for s in sources] + +Return('sources') diff --git a/src/dev/alpha_access.h b/src/dev/alpha/access.h index 4adeaf84b..4adeaf84b 100644 --- a/src/dev/alpha_access.h +++ b/src/dev/alpha/access.h diff --git a/src/dev/alpha_console.cc b/src/dev/alpha/console.cc index 40868de51..f077efe6c 100644 --- a/src/dev/alpha_console.cc +++ b/src/dev/alpha/console.cc @@ -44,7 +44,7 @@ #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" -#include "dev/alpha_console.hh" +#include "dev/alpha/console.hh" #include "dev/platform.hh" #include "dev/simconsole.hh" #include "dev/simple_disk.hh" diff --git a/src/dev/alpha_console.hh b/src/dev/alpha/console.hh index 7d6d1e679..b8d21ad5d 100644 --- a/src/dev/alpha_console.hh +++ b/src/dev/alpha/console.hh @@ -36,7 +36,7 @@ #define __ALPHA_CONSOLE_HH__ #include "base/range.hh" -#include "dev/alpha_access.h" +#include "dev/alpha/access.h" #include "dev/io_device.hh" #include "sim/host.hh" #include "sim/sim_object.hh" diff --git a/src/dev/tsunami.cc b/src/dev/alpha/tsunami.cc index 8e740a72f..608e88846 100644 --- a/src/dev/tsunami.cc +++ b/src/dev/alpha/tsunami.cc @@ -38,10 +38,10 @@ #include "cpu/intr_control.hh" #include "dev/simconsole.hh" -#include "dev/tsunami_cchip.hh" -#include "dev/tsunami_pchip.hh" -#include "dev/tsunami_io.hh" -#include "dev/tsunami.hh" +#include "dev/alpha/tsunami_cchip.hh" +#include "dev/alpha/tsunami_pchip.hh" +#include "dev/alpha/tsunami_io.hh" +#include "dev/alpha/tsunami.hh" #include "sim/builder.hh" #include "sim/system.hh" diff --git a/src/dev/tsunami.hh b/src/dev/alpha/tsunami.hh index 6fbfac851..6fbfac851 100644 --- a/src/dev/tsunami.hh +++ b/src/dev/alpha/tsunami.hh diff --git a/src/dev/tsunami_cchip.cc b/src/dev/alpha/tsunami_cchip.cc index 74a68566c..924e1d462 100644 --- a/src/dev/tsunami_cchip.cc +++ b/src/dev/alpha/tsunami_cchip.cc @@ -41,9 +41,9 @@ #include "base/trace.hh" #include "cpu/intr_control.hh" #include "cpu/thread_context.hh" -#include "dev/tsunami.hh" -#include "dev/tsunami_cchip.hh" -#include "dev/tsunamireg.h" +#include "dev/alpha/tsunami.hh" +#include "dev/alpha/tsunami_cchip.hh" +#include "dev/alpha/tsunamireg.h" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "mem/port.hh" diff --git a/src/dev/tsunami_cchip.hh b/src/dev/alpha/tsunami_cchip.hh index 297a94129..004c3cd29 100644 --- a/src/dev/tsunami_cchip.hh +++ b/src/dev/alpha/tsunami_cchip.hh @@ -35,7 +35,7 @@ #ifndef __TSUNAMI_CCHIP_HH__ #define __TSUNAMI_CCHIP_HH__ -#include "dev/tsunami.hh" +#include "dev/alpha/tsunami.hh" #include "base/range.hh" #include "dev/io_device.hh" diff --git a/src/dev/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index 73af6c2ef..def214a95 100644 --- a/src/dev/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -43,10 +43,10 @@ #include "base/trace.hh" #include "dev/pitreg.h" #include "dev/rtcreg.h" -#include "dev/tsunami_cchip.hh" -#include "dev/tsunami.hh" -#include "dev/tsunami_io.hh" -#include "dev/tsunamireg.h" +#include "dev/alpha/tsunami_cchip.hh" +#include "dev/alpha/tsunami.hh" +#include "dev/alpha/tsunami_io.hh" +#include "dev/alpha/tsunamireg.h" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "mem/port.hh" diff --git a/src/dev/tsunami_io.hh b/src/dev/alpha/tsunami_io.hh index 5ea3628c1..54acefc25 100644 --- a/src/dev/tsunami_io.hh +++ b/src/dev/alpha/tsunami_io.hh @@ -39,7 +39,7 @@ #include "dev/io_device.hh" #include "base/range.hh" -#include "dev/tsunami.hh" +#include "dev/alpha/tsunami.hh" #include "sim/eventq.hh" /** diff --git a/src/dev/tsunami_pchip.cc b/src/dev/alpha/tsunami_pchip.cc index 549db1a50..94a7f96e5 100644 --- a/src/dev/tsunami_pchip.cc +++ b/src/dev/alpha/tsunami_pchip.cc @@ -38,9 +38,9 @@ #include <vector> #include "base/trace.hh" -#include "dev/tsunami_pchip.hh" -#include "dev/tsunamireg.h" -#include "dev/tsunami.hh" +#include "dev/alpha/tsunami_pchip.hh" +#include "dev/alpha/tsunamireg.h" +#include "dev/alpha/tsunami.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "sim/builder.hh" diff --git a/src/dev/tsunami_pchip.hh b/src/dev/alpha/tsunami_pchip.hh index d0a9c3157..1632a36d4 100644 --- a/src/dev/tsunami_pchip.hh +++ b/src/dev/alpha/tsunami_pchip.hh @@ -35,7 +35,7 @@ #ifndef __TSUNAMI_PCHIP_HH__ #define __TSUNAMI_PCHIP_HH__ -#include "dev/tsunami.hh" +#include "dev/alpha/tsunami.hh" #include "base/range.hh" #include "dev/io_device.hh" diff --git a/src/dev/tsunamireg.h b/src/dev/alpha/tsunamireg.h index d603972be..d603972be 100644 --- a/src/dev/tsunamireg.h +++ b/src/dev/alpha/tsunamireg.h diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc index 5d3346b1e..5083c9c8d 100644 --- a/src/dev/ide_disk.cc +++ b/src/dev/ide_disk.cc @@ -44,8 +44,8 @@ #include "dev/disk_image.hh" #include "dev/ide_disk.hh" #include "dev/ide_ctrl.hh" -#include "dev/tsunami.hh" -#include "dev/tsunami_pchip.hh" +#include "dev/alpha/tsunami.hh" +#include "dev/alpha/tsunami_pchip.hh" #include "sim/builder.hh" #include "sim/sim_object.hh" #include "sim/root.hh" diff --git a/src/dev/isa_fake.hh b/src/dev/isa_fake.hh index c4072e42c..4c195a97f 100644 --- a/src/dev/isa_fake.hh +++ b/src/dev/isa_fake.hh @@ -37,7 +37,7 @@ #include "base/range.hh" #include "dev/io_device.hh" -#include "dev/tsunami.hh" +#include "dev/alpha/tsunami.hh" #include "mem/packet.hh" /** diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index 8c0d03817..383fc494f 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -45,7 +45,7 @@ #include "base/trace.hh" #include "dev/pciconfigall.hh" #include "dev/pcidev.hh" -#include "dev/tsunamireg.h" +#include "dev/alpha/tsunamireg.h" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "sim/builder.hh" diff --git a/src/dev/sparc/SConscript b/src/dev/sparc/SConscript new file mode 100644 index 000000000..701e533a8 --- /dev/null +++ b/src/dev/sparc/SConscript @@ -0,0 +1,46 @@ +# -*- mode:python -*- + +# 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 +# Gabe Black + +import os.path, sys + +# Import build environment variable from SConstruct. +Import('env') + +sources = [] + +sources += Split(''' + ''') + +# Convert file names to SCons File objects. This takes care of the +# path relative to the top of the directory tree. +sources = [File(s) for s in sources] + +Return('sources') diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index 9051a26a2..ddee33695 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -35,7 +35,6 @@ #include <string> #include <vector> -#include "arch/alpha/ev5.hh" #include "base/inifile.hh" #include "base/str.hh" // for to_number #include "base/trace.hh" diff --git a/src/dev/uart8250.hh b/src/dev/uart8250.hh index 2e768216a..a0620c7e0 100644 --- a/src/dev/uart8250.hh +++ b/src/dev/uart8250.hh @@ -35,7 +35,7 @@ #ifndef __DEV_UART8250_HH__ #define __DEV_UART8250_HH__ -#include "dev/tsunamireg.h" +#include "dev/alpha/tsunamireg.h" #include "base/range.hh" #include "dev/io_device.hh" #include "dev/uart.hh" diff --git a/src/kern/linux/events.cc b/src/kern/linux/events.cc index 289ece5ce..ba52e040a 100644 --- a/src/kern/linux/events.cc +++ b/src/kern/linux/events.cc @@ -49,7 +49,7 @@ DebugPrintkEvent::process(ThreadContext *tc) DPRINTFN(""); } - AlphaISA::AlphaArguments args(tc); + TheISA::Arguments args(tc); Printk(args); SkipFuncEvent::process(tc); } diff --git a/src/kern/linux/printk.cc b/src/kern/linux/printk.cc index 004d1be2f..ea3d59f19 100644 --- a/src/kern/linux/printk.cc +++ b/src/kern/linux/printk.cc @@ -39,7 +39,7 @@ using namespace std; void -Printk(AlphaISA::AlphaArguments args) +Printk(TheISA::Arguments args) { char *p = (char *)args++; diff --git a/src/kern/linux/printk.hh b/src/kern/linux/printk.hh index 5ddf0a018..17d59b765 100644 --- a/src/kern/linux/printk.hh +++ b/src/kern/linux/printk.hh @@ -32,8 +32,10 @@ #ifndef __PRINTK_HH__ #define __PRINTK_HH__ -class AlphaISA::AlphaArguments; +#include "arch/isa_specific.hh" -void Printk(AlphaISA::AlphaArguments args); +class TheISA::Arguments; + +void Printk(TheISA::Arguments args); #endif // __PRINTK_HH__ diff --git a/src/kern/tru64/dump_mbuf.cc b/src/kern/tru64/dump_mbuf.cc index 8f88f8904..22d2228f0 100644 --- a/src/kern/tru64/dump_mbuf.cc +++ b/src/kern/tru64/dump_mbuf.cc @@ -47,7 +47,7 @@ using namespace TheISA; namespace tru64 { void -DumpMbuf(AlphaArguments args) +DumpMbuf(Arguments args) { ThreadContext *tc = args.getThreadContext(); Addr addr = (Addr)args; diff --git a/src/kern/tru64/dump_mbuf.hh b/src/kern/tru64/dump_mbuf.hh index 25c6fd31d..30b1102b9 100644 --- a/src/kern/tru64/dump_mbuf.hh +++ b/src/kern/tru64/dump_mbuf.hh @@ -34,7 +34,7 @@ #include "arch/arguments.hh" namespace tru64 { - void DumpMbuf(AlphaISA::AlphaArguments args); + void DumpMbuf(TheISA::Arguments args); } #endif // __DUMP_MBUF_HH__ diff --git a/src/kern/tru64/printf.cc b/src/kern/tru64/printf.cc index 29dd443d2..2c767c4d2 100644 --- a/src/kern/tru64/printf.cc +++ b/src/kern/tru64/printf.cc @@ -42,7 +42,7 @@ using namespace std; namespace tru64 { void -Printf(AlphaISA::AlphaArguments args) +Printf(TheISA::Arguments args) { char *p = (char *)args++; diff --git a/src/kern/tru64/printf.hh b/src/kern/tru64/printf.hh index f6a4544ad..ff453b1c1 100644 --- a/src/kern/tru64/printf.hh +++ b/src/kern/tru64/printf.hh @@ -34,7 +34,7 @@ #include "arch/arguments.hh" namespace tru64 { - void Printf(AlphaISA::AlphaArguments args); + void Printf(TheISA::Arguments args); } #endif // __PRINTF_HH__ diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc index 69638bde1..851b3a526 100644 --- a/src/kern/tru64/tru64_events.cc +++ b/src/kern/tru64/tru64_events.cc @@ -81,7 +81,7 @@ PrintfEvent::process(ThreadContext *tc) if (DTRACE(Printf)) { DebugOut() << curTick << ": " << tc->getCpuPtr()->name() << ": "; - AlphaArguments args(tc); + Arguments args(tc); tru64::Printf(args); } } @@ -93,7 +93,7 @@ DebugPrintfEvent::process(ThreadContext *tc) if (!raw) DebugOut() << curTick << ": " << tc->getCpuPtr()->name() << ": "; - AlphaArguments args(tc); + Arguments args(tc); tru64::Printf(args); } } @@ -102,7 +102,7 @@ void DumpMbufEvent::process(ThreadContext *tc) { if (DTRACE(DebugPrintf)) { - AlphaArguments args(tc); + Arguments args(tc); tru64::DumpMbuf(args); } } diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index d913e159b..548d0c167 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -134,18 +134,6 @@ namespace AlphaPseudo } void - ivlb(ThreadContext *tc) - { - if (tc->getKernelStats()) - tc->getKernelStats()->ivlb(); - } - - void - ivle(ThreadContext *tc) - { - } - - void m5exit_old(ThreadContext *tc) { exitSimLoop("m5_exit_old instruction encountered"); diff --git a/src/sim/system.cc b/src/sim/system.cc index 11ae492b9..4b42d41fc 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -43,7 +43,7 @@ #include "sim/system.hh" #if FULL_SYSTEM #include "arch/vtophys.hh" -#include "base/remote_gdb.hh" +#include "arch/remote_gdb.hh" #include "kern/kernel_stats.hh" #endif diff --git a/src/sim/system.hh b/src/sim/system.hh index 827fe5c78..b3a67bf7a 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -56,7 +56,10 @@ class PhysicalMemory; #if FULL_SYSTEM class Platform; class GDBListener; -class RemoteGDB; +namespace TheISA +{ + class RemoteGDB; +} #endif class System : public SimObject @@ -157,7 +160,7 @@ class System : public SimObject #endif public: #if FULL_SYSTEM - std::vector<RemoteGDB *> remoteGDB; + std::vector<TheISA::RemoteGDB *> remoteGDB; std::vector<GDBListener *> gdbListen; virtual bool breakpoint() = 0; #endif // FULL_SYSTEM |