/*
- * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * 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
#include <sys/signal.h>
-#include <unistd.h>
-
#include <cstdio>
#include <string>
+#include <unistd.h>
-#include "cpu/exec_context.hh"
#include "base/intmath.hh"
#include "base/kgdb.h"
-
-#include "mem/functional_mem/physical_memory.hh"
#include "base/remote_gdb.hh"
#include "base/socket.hh"
#include "base/trace.hh"
-#include "targetarch/vtophys.hh"
-#include "sim/system.hh"
+#include "cpu/exec_context.hh"
#include "cpu/static_inst.hh"
+#include "mem/functional/physical.hh"
+#include "sim/system.hh"
+#include "targetarch/vtophys.hh"
using namespace std;
-#ifdef DEBUG
-RemoteGDB *theDebugger = NULL;
+#ifndef NDEBUG
+vector<RemoteGDB *> debuggers;
+int current_debugger = -1;
void
debugger()
{
- if (theDebugger)
- theDebugger->trap(ALPHA_KENTRY_IF);
+ if (current_debugger >= 0 && current_debugger < debuggers.size()) {
+ RemoteGDB *gdb = debuggers[current_debugger];
+ if (!gdb->isattached())
+ gdb->listener->accept();
+ if (gdb->isattached())
+ gdb->trap(ALPHA_KENTRY_IF);
+ }
}
#endif
GDBListener::GDBListener(RemoteGDB *g, int p)
: event(NULL), gdb(g), port(p)
-{}
+{
+ assert(!gdb->listener);
+ gdb->listener = this;
+}
GDBListener::~GDBListener()
{
port++;
}
- cerr << "Listening for remote gdb connection on port " << port << endl;
event = new Event(this, listener.getfd(), POLLIN);
pollQueue.schedule(event);
+
+#ifndef NDEBUG
+ gdb->number = debuggers.size();
+ debuggers.push_back(gdb);
+#endif
+
+#ifndef NDEBUG
+ ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n",
+ curTick, name(), gdb->number, port);
+#else
+ ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n",
+ curTick, name(), port);
+#endif
}
void
}
RemoteGDB::RemoteGDB(System *_system, ExecContext *c)
- : event(NULL), fd(-1), active(false), attached(false),
+ : event(NULL), listener(NULL), number(-1), fd(-1),
+ active(false), attached(false),
system(_system), pmem(_system->physmem), context(c)
{
memset(gdbregs, 0, sizeof(gdbregs));
attached = true;
DPRINTFN("remote gdb attached\n");
-#ifdef DEBUG
- theDebugger = this;
-#endif
}
void
RemoteGDB::acc(Addr va, size_t len)
{
Addr last_va;
- Addr pte;
- va = alpha_trunc_page(va);
- last_va = alpha_round_page(va + len);
+ va = TheISA::TruncPage(va);
+ last_va = TheISA::RoundPage(va + len);
do {
- if (va >= ALPHA_K0SEG_BASE && va < ALPHA_K1SEG_BASE) {
- if (va < (ALPHA_K0SEG_BASE + pmem->size())) {
+ if (TheISA::IsK0Seg(va)) {
+ if (va < (TheISA::K0SegBase + pmem->size())) {
DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
"%#x < K0SEG + size\n", va);
return true;
* but there is no easy way to do it.
*/
- if (PC_PAL(va) || va < 0x10000)
+ if (AlphaISA::PcPAL(va) || va < 0x10000)
return true;
Addr ptbr = context->regs.ipr[AlphaISA::IPR_PALtemp20];
- pte = kernel_pte_lookup(pmem, ptbr, va);
- if (!pte || !entry_valid(pmem->phys_read_qword(pte))) {
+ TheISA::PageTableEntry pte = kernel_pte_lookup(pmem, ptbr, va);
+ if (!pte.valid()) {
DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
return false;
}
- va += ALPHA_PGBYTES;
+ va += TheISA::PageBytes;
} while (va < last_va);
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
gdb(_gdb), refcount(0)
{
DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
- schedule();
}
void
active = true;
else
// Tell remote host that an exception has occurred.
- sprintf((char *)buffer, "S%02x", signal(type));
+ snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
send(buffer);
// Stick frame regs into our reg cache.
// 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".
- sprintf((char *)buffer, "S%02x", signal(type));
+ snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
send(buffer);
continue;