Remote GDB support has been changed to use inheritance. Alpha should work, but isn...
authorGabe Black <gblack@eecs.umich.edu>
Mon, 6 Nov 2006 23:29:58 +0000 (18:29 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Mon, 6 Nov 2006 23:29:58 +0000 (18:29 -0500)
--HG--
extra : convert_revision : fc7e1e73e2f3b1a4ab9905a1eb98c5f07c6c8707

13 files changed:
src/arch/SConscript
src/arch/alpha/SConscript
src/arch/alpha/ev5.cc
src/arch/alpha/remote_gdb.cc [new file with mode: 0644]
src/arch/alpha/remote_gdb.hh [new file with mode: 0644]
src/arch/alpha/system.cc
src/arch/sparc/remote_gdb.cc [new file with mode: 0644]
src/arch/sparc/remote_gdb.hh [new file with mode: 0644]
src/base/remote_gdb.cc
src/base/remote_gdb.hh
src/cpu/o3/fetch_impl.hh
src/sim/system.cc
src/sim/system.hh

index 092fad225543b08a848bbce3d44f9dbe38f6f458..2ef3d5ee0d30b2d434478a3236b838ea48054757 100644 (file)
@@ -54,6 +54,7 @@ isa_switch_hdrs = Split('''
         locked_mem.hh
        process.hh
        regfile.hh
+       remote_gdb.hh
        stacktrace.hh
        syscallreturn.hh
        tlb.hh
index 9a5680649edd2d64fdc1954beedc0f86b1833a94..2d733d73bf4047fe87eed7f036607690b7cc3bba 100644 (file)
@@ -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
index dca948bbdbfa5504ec7ecd3a3d0897c88c40f2e2..6f8f255b437840ef24844a88cf8b582d4249801f 100644 (file)
@@ -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"
diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc
new file mode 100644 (file)
index 0000000..96c7ea6
--- /dev/null
@@ -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 (file)
index 0000000..1dd4ada
--- /dev/null
@@ -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__ */
index 5597eaedcdf887d1ced7304c391dc126ec2ef036..710f6ef46e85db9de198d2da58d2c9c1e3c40300 100644 (file)
@@ -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/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc
new file mode 100644 (file)
index 0000000..2e662af
--- /dev/null
@@ -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 (file)
index 0000000..6ac4f29
--- /dev/null
@@ -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__ */
index e4efa31e3f11fc4466fb55e6cc59fef2319ca520..01166d46f213a7c9271175cfe8df72ba84582c90 100644 (file)
 
 #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;
index 8c3ce7572ec246f7b327168455a248578214dc0b..65e4313eb6e103b03ad80c1815f27e257d20da3a 100644 (file)
@@ -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
@@ -83,6 +132,23 @@ class RemoteGDB
     PhysicalMemory *pmem;
     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();
index 4c39341aa2b790bd32fc6d8610f1c085acc846ee..5ef6e27ea3f6f8a955fc69e6589d7c5cb515edf9 100644 (file)
@@ -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
 
index 11ae492b99c36976ecca019a8f57ac262aeae018..4b42d41fcc7e2b786b3da822e252dcd08d6c07dd 100644 (file)
@@ -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
 
index 827fe5c78a91d363014a6a187352952b18e22874..b3a67bf7a74d8fbcd4f717896257de7d450f3344 100644 (file)
@@ -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