diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index cb43419479..bd702e2de4 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -146,9 +146,6 @@ class BaseCPU(ClockedObject): do_statistics_insts = Param.Bool(True, "enable statistics pseudo instructions") - wait_for_remote_gdb = Param.Bool(False, - "Wait for a remote GDB connection"); - workload = VectorParam.Process([], "processes to run") mmu = Param.BaseMMU(ArchMMU(), "CPU memory management unit") diff --git a/src/cpu/base.cc b/src/cpu/base.cc index dffe4c9ce1..317844dcaa 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -725,12 +725,6 @@ BaseCPU::traceFunctionsInternal(Addr pc) } } -bool -BaseCPU::waitForRemoteGDB() const -{ - return params().wait_for_remote_gdb; -} - BaseCPU::GlobalStats::GlobalStats(::Stats::Group *parent) : ::Stats::Group(parent), diff --git a/src/cpu/base.hh b/src/cpu/base.hh index c113829a7f..177d3df36e 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -609,8 +609,6 @@ class BaseCPU : public ClockedObject return &addressMonitor[tid]; } - bool waitForRemoteGDB() const; - Cycles syscallRetryLatency; // Enables CPU to enter power gating on a configurable cycle count diff --git a/src/sim/Workload.py b/src/sim/Workload.py index 4f1b1b56e8..91c1c55a22 100644 --- a/src/sim/Workload.py +++ b/src/sim/Workload.py @@ -33,6 +33,9 @@ class Workload(SimObject): cxx_header = "sim/workload.hh" abstract = True + wait_for_remote_gdb = Param.Bool(False, + "Wait for a remote GDB connection"); + class KernelWorkload(Workload): type = 'KernelWorkload' cxx_header = "sim/kernel_workload.hh" diff --git a/src/sim/system.cc b/src/sim/system.cc index 7f81f5184b..2abebdb326 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -43,7 +43,6 @@ #include -#include "arch/remote_gdb.hh" #include "base/compiler.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" @@ -124,13 +123,6 @@ System::Threads::insert(ThreadContext *tc, ContextID id) // been reallocated. t.resumeEvent = new EventFunctionWrapper( [this, id](){ thread(id).resume(); }, sys->name()); -# if THE_ISA != NULL_ISA - int port = getRemoteGDBPort(); - if (port) { - t.gdb = new TheISA::RemoteGDB(sys, tc, port + id); - t.gdb->listen(); - } -# endif } void @@ -138,8 +130,6 @@ System::Threads::replace(ThreadContext *tc, ContextID id) { auto &t = thread(id); panic_if(!t.context, "Can't replace a context which doesn't exist."); - if (t.gdb) - t.gdb->replaceThreadContext(tc); # if THE_ISA != NULL_ISA if (t.resumeEvent->scheduled()) { Tick when = t.resumeEvent->when(); @@ -277,26 +267,6 @@ System::~System() delete workItemStats[j]; } -void -System::startup() -{ - SimObject::startup(); - - // Now that we're about to start simulation, wait for GDB connections if - // requested. -#if THE_ISA != NULL_ISA - for (int i = 0; i < threads.size(); i++) { - auto *gdb = threads.thread(i).gdb; - auto *cpu = threads[i]->getCpuPtr(); - if (gdb && cpu->waitForRemoteGDB()) { - inform("%s: Waiting for a remote GDB connection on port %d.", - cpu->name(), gdb->port()); - gdb->connect(); - } - } -#endif -} - Port & System::getPort(const std::string &if_name, PortID idx) { @@ -520,11 +490,7 @@ System::workItemEnd(uint32_t tid, uint32_t workid) bool System::trapToGdb(int signal, ContextID ctx_id) const { - auto *gdb = threads.thread(ctx_id).gdb; - if (!gdb) - return false; - gdb->trap(ctx_id, signal); - return true; + return workload && workload->trapToGdb(signal, ctx_id); } void diff --git a/src/sim/system.hh b/src/sim/system.hh index d04c3d2148..cbbd5e5573 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -119,7 +119,6 @@ class System : public SimObject, public PCEventScope { ThreadContext *context = nullptr; bool active = false; - BaseRemoteGDB *gdb = nullptr; Event *resumeEvent = nullptr; void resume(); @@ -231,8 +230,6 @@ class System : public SimObject, public PCEventScope const_iterator end() const { return const_iterator(*this, size()); } }; - void startup() override; - /** * Get a reference to the system port that can be used by * non-structural simulation objects like processes or threads, or diff --git a/src/sim/workload.cc b/src/sim/workload.cc index c7dfcd4a3c..d1ce8b554b 100644 --- a/src/sim/workload.cc +++ b/src/sim/workload.cc @@ -27,7 +27,10 @@ #include "sim/workload.hh" +#include "arch/remote_gdb.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" +#include "sim/debug.hh" void Workload::registerThreadContext(ThreadContext *tc) @@ -37,6 +40,16 @@ Workload::registerThreadContext(ThreadContext *tc) std::tie(it, success) = threads.insert(tc); panic_if(!success, "Failed to add thread context %d.", tc->contextId()); + +# if THE_ISA != NULL_ISA + int port = getRemoteGDBPort(); + if (port && !gdb) { + gdb = new TheISA::RemoteGDB(system, tc, port); + gdb->listen(); + } else if (gdb) { + gdb->addThreadContext(tc); + } +# endif } void @@ -54,7 +67,39 @@ Workload::replaceThreadContext(ThreadContext *tc) std::tie(it, success) = threads.insert(tc); panic_if(!success, "Failed to insert replacement thread context %d.", id); + + if (gdb) + gdb->replaceThreadContext(tc); + return; } panic("Replacement thread context %d doesn't match any known id.", id); } + +bool +Workload::trapToGdb(int signal, ContextID ctx_id) +{ +# if THE_ISA != NULL_ISA + if (gdb) { + gdb->trap(ctx_id, signal); + return true; + } +# endif + return false; +}; + +void +Workload::startup() +{ + SimObject::startup(); + +# if THE_ISA != NULL_ISA + // Now that we're about to start simulation, wait for GDB connections if + // requested. + if (gdb && waitForRemoteGDB) { + inform("%s: Waiting for a remote GDB connection on port %d.", name(), + gdb->port()); + gdb->connect(); + } +# endif +} diff --git a/src/sim/workload.hh b/src/sim/workload.hh index ff29e2d5fd..b6345257f1 100644 --- a/src/sim/workload.hh +++ b/src/sim/workload.hh @@ -37,6 +37,7 @@ #include "sim/sim_object.hh" #include "sim/stats.hh" +class BaseRemoteGDB; class System; class ThreadContext; @@ -66,20 +67,29 @@ class Workload : public SimObject {} } stats; + BaseRemoteGDB *gdb = nullptr; + bool waitForRemoteGDB = false; std::set threads; public: - Workload(const WorkloadParams ¶ms) : SimObject(params), stats(this) + Workload(const WorkloadParams ¶ms) : SimObject(params), stats(this), + waitForRemoteGDB(params.wait_for_remote_gdb) {} void recordQuiesce() { stats.instStats.quiesce++; } void recordArm() { stats.instStats.arm++; } + // Once trapping into GDB is no longer a special case routed through the + // system object, this helper can be removed. + bool trapToGdb(int signal, ContextID ctx_id); + System *system = nullptr; virtual void registerThreadContext(ThreadContext *tc); virtual void replaceThreadContext(ThreadContext *tc); + void startup() override; + virtual Addr getEntry() const = 0; virtual Loader::Arch getArch() const = 0;