From 9023f5c96d0a248399fce0f664136d164f0e561f Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 20 Aug 2004 11:35:31 -0400 Subject: [PATCH] - Clean up and factor out all of the binning code into a single place so it's easier to work with. - Add support for binning kernel/user/idle time separately from lisa's binning stuff, but make the two compatible. - KernelStats used to directly implement the pImpl idiom, but it makes more sense to just remove the level of indirection and make the exec context have a pointer to the stats. - Factor common code out of LinuxSystem and Tru64System and put it into the System base class. While doing that, make all constructors take a pointer to a parameter struct instead of naming the parameters individually to make it much easier to add parameters to these classes. SConscript: Move the function tracking and binning stuff around. arch/alpha/ev5.cc: kernelStats is now a pointer arch/alpha/pseudo_inst.cc: kernelStats is now a pointer the parameters to the system have been moved into their own struct base/trace.hh: provide a little functor class for wrapping a string that can allow you to define name() in any scope very simply for use with DPRINTF cpu/base_cpu.cc: New order of arguments for consistency. cpu/exec_context.cc: kernelStats no longer has the level of indirection in it, execContext has the indirection now. so, kernelStats is a pointer. We also need a pointer to the kernelBinning stuff from the system and we need to figure out if we want to do binning or not. Move a whole bunch of code into kern_binning.cc so it's all in the same place. cpu/exec_context.hh: We want pointers to the kernel binning/stats stuff and we'll have the exec_context and system have the level of indirection instead of having the extra layer in the kernel stats class. cpu/simple_cpu/simple_cpu.cc: call through the exec context to do the special binning stuff. kern/kernel_stats.cc: kern/kernel_stats.hh: Re-organize the stats stuff and remove the level of indirection (that was there to simplify building) and move the binning stuff into its own class/file. kern/linux/linux_system.cc: kern/linux/linux_system.hh: kern/tru64/tru64_system.cc: kern/tru64/tru64_system.hh: sim/system.cc: sim/system.hh: move lots of common system code into the base system class so that it can be shared between linux, tru64, and whatever else we decide to support in the future. Make the constructor take a pointer to a parameter struct so that it is easier to pass parameters to the parent. kern/system_events.cc: move the majority of the binning code into the Kernel::Binning class in the kern_binning file kern/system_events.hh: FnEvents only need to know the bin create the Idle start event to find the PCBB of the idle process when it starts. kern/tru64/tru64_events.cc: memCtrl -> memctrl sim/process.cc: sim/process.hh: re-order args for consistency --HG-- extra : convert_revision : 86cb39738c41fcd680f2aad125c9dde000227b2b --- SConscript | 2 +- arch/alpha/ev5.cc | 13 +- arch/alpha/pseudo_inst.cc | 9 +- base/trace.hh | 10 +- cpu/base_cpu.cc | 4 +- cpu/exec_context.cc | 90 +++------- cpu/exec_context.hh | 25 ++- cpu/simple_cpu/simple_cpu.cc | 5 +- kern/kernel_stats.cc | 311 ++++++++++++-------------------- kern/kernel_stats.hh | 158 +++++++++++++++-- kern/linux/linux_system.cc | 266 +++++++--------------------- kern/linux/linux_system.hh | 103 +++-------- kern/system_events.cc | 54 +----- kern/system_events.hh | 15 +- kern/tru64/tru64_events.cc | 2 +- kern/tru64/tru64_system.cc | 213 +++++----------------- kern/tru64/tru64_system.hh | 56 +----- sim/process.cc | 2 +- sim/process.hh | 2 +- sim/system.cc | 332 ++++++++++++++++------------------- sim/system.hh | 128 +++++++++----- 21 files changed, 718 insertions(+), 1082 deletions(-) diff --git a/SConscript b/SConscript index 0f2d90c2d..f22c85059 100644 --- a/SConscript +++ b/SConscript @@ -190,7 +190,6 @@ base_sources = Split(''' sim/sim_object.cc sim/stat_context.cc sim/stat_control.cc - sim/sw_context.cc sim/trace_context.cc sim/universe.cc sim/pyconfig/pyconfig.cc @@ -288,6 +287,7 @@ full_system_sources = Split(''' dev/tsunami_pchip.cc dev/uart.cc + kern/kernel_binning.cc kern/kernel_stats.cc kern/system_events.cc kern/linux/linux_events.cc diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc index b043ed0ee..b0f2251dc 100644 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@ -9,6 +9,7 @@ #include "cpu/base_cpu.hh" #include "cpu/exec_context.hh" #include "cpu/fast_cpu/fast_cpu.hh" +#include "kern/kernel_stats.hh" #include "sim/debug.hh" #include "sim/sim_events.hh" @@ -167,7 +168,7 @@ ExecContext::ev5_trap(Fault fault) cpu->recordEvent(csprintf("Fault %s", FaultName(fault))); assert(!misspeculating()); - kernelStats.fault(fault); + kernelStats->fault(fault); if (fault == Arithmetic_Fault) panic("Arithmetic traps are unimplemented!"); @@ -232,7 +233,7 @@ ExecContext::hwrei() setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]); if (!misspeculating()) { - kernelStats.hwrei(); + kernelStats->hwrei(); if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0) AlphaISA::swap_palshadow(®s, false); @@ -415,7 +416,7 @@ ExecContext::setIpr(int idx, uint64_t val) // write entire quad w/ no side-effect old = ipr[idx]; ipr[idx] = val; - kernelStats.context(old, val); + kernelStats->context(old, val); break; case AlphaISA::IPR_DTB_PTE: @@ -442,11 +443,11 @@ ExecContext::setIpr(int idx, uint64_t val) // only write least significant five bits - interrupt level ipr[idx] = val & 0x1f; - kernelStats.swpipl(ipr[idx]); + kernelStats->swpipl(ipr[idx]); break; case AlphaISA::IPR_DTB_CM: - kernelStats.mode((val & 0x18) != 0); + kernelStats->mode((val & 0x18) != 0); case AlphaISA::IPR_ICM: // only write two mode bits - processor mode @@ -622,7 +623,7 @@ ExecContext::setIpr(int idx, uint64_t val) bool ExecContext::simPalCheck(int palFunc) { - kernelStats.callpal(palFunc); + kernelStats->callpal(palFunc); switch (palFunc) { case PAL::halt: diff --git a/arch/alpha/pseudo_inst.cc b/arch/alpha/pseudo_inst.cc index fd6742801..95c85b45a 100644 --- a/arch/alpha/pseudo_inst.cc +++ b/arch/alpha/pseudo_inst.cc @@ -37,6 +37,7 @@ #include "cpu/base_cpu.hh" #include "cpu/sampling_cpu/sampling_cpu.hh" #include "cpu/exec_context.hh" +#include "kern/kernel_stats.hh" #include "sim/param.hh" #include "sim/serialize.hh" #include "sim/sim_exit.hh" @@ -60,7 +61,7 @@ namespace AlphaPseudo void arm(ExecContext *xc) { - xc->kernelStats.arm(); + xc->kernelStats->arm(); } void @@ -70,13 +71,13 @@ namespace AlphaPseudo return; xc->suspend(); - xc->kernelStats.quiesce(); + xc->kernelStats->quiesce(); } void ivlb(ExecContext *xc) { - xc->kernelStats.ivlb(); + xc->kernelStats->ivlb(); } void @@ -164,7 +165,7 @@ namespace AlphaPseudo void readfile(ExecContext *xc) { - const string &file = xc->cpu->system->readfile; + const string &file = xc->cpu->system->params->readfile; if (file.empty()) { xc->regs.intRegFile[0] = ULL(0); return; diff --git a/base/trace.hh b/base/trace.hh index 1aadb36cf..5e05d6e5e 100644 --- a/base/trace.hh +++ b/base/trace.hh @@ -157,8 +157,16 @@ namespace Trace { extern const std::string DefaultName; }; -inline const std::string &name() { return Trace::DefaultName; } +// This silly little class allows us to wrap a string in a functor +// object so that we can give a name() that DPRINTF will like +struct StringWrap +{ + std::string str; + StringWrap(const std::string &s) : str(s) {} + const std::string &operator()() const { return str; } +}; +inline const std::string &name() { return Trace::DefaultName; } std::ostream &DebugOut(); // diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc index 3ee7a3892..8a9c9a102 100644 --- a/cpu/base_cpu.cc +++ b/cpu/base_cpu.cc @@ -185,10 +185,10 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) newXC->takeOverFrom(oldXC); assert(newXC->cpu_id == oldXC->cpu_id); #ifdef FULL_SYSTEM - system->replaceExecContext(newXC->cpu_id, newXC); + system->replaceExecContext(newXC, newXC->cpu_id); #else assert(newXC->process == oldXC->process); - newXC->process->replaceExecContext(newXC->cpu_id, newXC); + newXC->process->replaceExecContext(newXC, newXC->cpu_id); #endif } diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc index 9c21b3a56..1cb33f13e 100644 --- a/cpu/exec_context.cc +++ b/cpu/exec_context.cc @@ -32,6 +32,9 @@ #include "cpu/exec_context.hh" #ifdef FULL_SYSTEM +#include "base/cprintf.hh" +#include "kern/kernel_stats.hh" +#include "sim/serialize.hh" #include "sim/system.hh" #else #include "sim/process.hh" @@ -44,12 +47,13 @@ using namespace std; ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_mem) - : _status(ExecContext::Unallocated), - kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num), + : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys), - memCtrl(_sys->memCtrl), physmem(_sys->physmem), - swCtx(NULL), func_exe_inst(0), storeCondFailures(0) + memctrl(_sys->memctrl), physmem(_sys->physmem), + kernelBinning(system->kernelBinning), bin(kernelBinning->bin), + fnbin(kernelBinning->fnbin), func_exe_inst(0), storeCondFailures(0) { + kernelStats = new Kernel::Statistics(this); memset(®s, 0, sizeof(RegFile)); } #else @@ -72,6 +76,13 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, } #endif +ExecContext::~ExecContext() +{ +#ifdef FULL_SYSTEM + delete kernelStats; +#endif +} + void ExecContext::takeOverFrom(ExecContext *oldContext) @@ -86,9 +97,6 @@ ExecContext::takeOverFrom(ExecContext *oldContext) // copy over functional state _status = oldContext->_status; -#ifdef FULL_SYSTEM - kernelStats = oldContext->kernelStats; -#endif regs = oldContext->regs; cpu_id = oldContext->cpu_id; func_exe_inst = oldContext->func_exe_inst; @@ -98,6 +106,14 @@ ExecContext::takeOverFrom(ExecContext *oldContext) oldContext->_status = ExecContext::Unallocated; } +#ifdef FULL_SYSTEM +void +ExecContext::execute(const StaticInstBase *inst) +{ + assert(kernelStats); + system->kernelBinning->execute(this, inst); +} +#endif void ExecContext::serialize(ostream &os) @@ -109,31 +125,8 @@ ExecContext::serialize(ostream &os) SERIALIZE_SCALAR(inst); #ifdef FULL_SYSTEM - bool ctx = false; - if (swCtx) { - ctx = true; - SERIALIZE_SCALAR(ctx); - SERIALIZE_SCALAR(swCtx->calls); - std::stack *stack = &(swCtx->callStack); - fnCall *top; - int size = stack->size(); - SERIALIZE_SCALAR(size); - - for (int j=0; jtop(); - paramOut(os, csprintf("stackpos[%d]",j), top->name); - delete top; - stack->pop(); - } - } else { - SERIALIZE_SCALAR(ctx); - } - if (system->bin) { - Stats::MainBin *cur = Stats::MainBin::curBin(); - string bin_name = cur->name(); - SERIALIZE_SCALAR(bin_name); - } -#endif //FULL_SYSTEM + kernelStats->serialize(os); +#endif } @@ -147,35 +140,8 @@ ExecContext::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(inst); #ifdef FULL_SYSTEM - bool ctx; - UNSERIALIZE_SCALAR(ctx); - if (ctx) { - swCtx = new SWContext; - UNSERIALIZE_SCALAR(swCtx->calls); - int size; - UNSERIALIZE_SCALAR(size); - - vector calls; - fnCall *call; - for (int i=0; iname); - call->myBin = system->getBin(call->name); - calls.push_back(call); - } - - for (int i=size-1; i>=0; --i) { - swCtx->callStack.push(calls[i]); - } - - } - - if (system->bin) { - string bin_name; - UNSERIALIZE_SCALAR(bin_name); - system->getBin(bin_name)->activate(); - } -#endif //FULL_SYSTEM + kernelStats->unserialize(cp, section); +#endif } @@ -232,7 +198,7 @@ void ExecContext::regStats(const string &name) { #ifdef FULL_SYSTEM - kernelStats.regStats(name + ".kern"); + kernelStats->regStats(name + ".kern"); #endif } diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index b47f5cd08..2ba2d7524 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -42,12 +42,12 @@ class BaseCPU; #ifdef FULL_SYSTEM +#include "sim/system.hh" #include "targetarch/alpha_memory.hh" -class MemoryController; -#include "kern/kernel_stats.hh" -#include "sim/system.hh" -#include "sim/sw_context.hh" +class MemoryController; +class StaticInstBase; +namespace Kernel { class Binning; class Statistics; } #else // !FULL_SYSTEM @@ -105,11 +105,6 @@ class ExecContext /// Set the status to Halted. void halt(); -#ifdef FULL_SYSTEM - public: - KernelStats kernelStats; -#endif - public: RegFile regs; // correct-path register context @@ -127,7 +122,6 @@ class ExecContext int cpu_id; #ifdef FULL_SYSTEM - FunctionalMemory *mem; AlphaITB *itb; AlphaDTB *dtb; @@ -136,10 +130,15 @@ class ExecContext // the following two fields are redundant, since we can always // look them up through the system pointer, but we'll leave them // here for now for convenience - MemoryController *memCtrl; + MemoryController *memctrl; PhysicalMemory *physmem; - SWContext *swCtx; + Kernel::Binning *kernelBinning; + Kernel::Statistics *kernelStats; + bool bin; + bool fnbin; + void execute(const StaticInstBase *inst); + #else Process *process; @@ -185,7 +184,7 @@ class ExecContext ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem, int _asid); #endif - virtual ~ExecContext() {} + virtual ~ExecContext(); virtual void takeOverFrom(ExecContext *oldContext); diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 6c22d7c81..449b20fee 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -733,9 +733,8 @@ SimpleCPU::tick() fault = si->execute(this, traceData); #ifdef FULL_SYSTEM - SWContext *ctx = xc->swCtx; - if (ctx) - ctx->process(xc, si.get()); + if (xc->fnbin) + xc->execute(si.get()); #endif if (si->isMemRef()) { diff --git a/kern/kernel_stats.cc b/kern/kernel_stats.cc index e6bcb4d29..c8c04e6d1 100644 --- a/kern/kernel_stats.cc +++ b/kern/kernel_stats.cc @@ -30,134 +30,82 @@ #include #include -#include "base/statistics.hh" +#include "arch/alpha/osfpal.hh" #include "base/trace.hh" +#include "base/statistics.hh" +#include "base/stats/bin.hh" #include "cpu/exec_context.hh" +#include "cpu/pc_event.hh" +#include "cpu/static_inst.hh" #include "kern/kernel_stats.hh" -#include "sim/stats.hh" -#include "sim/sw_context.hh" -#include "targetarch/isa_traits.hh" -#include "targetarch/osfpal.hh" -#include "targetarch/syscalls.hh" +#include "kern/linux/linux_syscalls.hh" using namespace std; using namespace Stats; -class KSData -{ - private: - string _name; - ExecContext *xc; - BaseCPU *cpu; - - public: - KSData(ExecContext *_xc, BaseCPU *_cpu) - : xc(_xc), cpu(_cpu), iplLast(0), iplLastTick(0), lastUser(false), - lastModeTick(0) - {} - - const string &name() { return _name; } - void regStats(const string &name); - - public: - Scalar<> _arm; - Scalar<> _quiesce; - Scalar<> _ivlb; - Scalar<> _ivle; - Scalar<> _hwrei; - - Vector<> _iplCount; - Vector<> _iplGood; - Vector<> _iplTicks; - Formula _iplUsed; - - Vector<> _callpal; - Vector<> _syscall; - Vector<> _faults; - - Vector<> _mode; - Vector<> _modeGood; - Formula _modeFraction; - Vector<> _modeTicks; - - Scalar<> _swap_context; - - private: - int iplLast; - Tick iplLastTick; - - bool lastUser; - Tick lastModeTick; - - public: - void swpipl(int ipl); - void mode(bool user); - void callpal(int code); -}; - -KernelStats::KernelStats(ExecContext *xc, BaseCPU *cpu) -{ data = new KSData(xc, cpu); } - -KernelStats::~KernelStats() -{ delete data; } +namespace Kernel { -void -KernelStats::regStats(const string &name) -{ data->regStats(name); } +const char *modestr[] = { "kernel", "user", "idle" }; + +Statistics::Statistics(ExecContext *context) + : xc(context), idleProcess((Addr)-1), themode(kernel), lastModeTick(0), + iplLast(0), iplLastTick(0) +{ +} void -KSData::regStats(const string &name) +Statistics::regStats(const string &_name) { - _name = name; + myname = _name; _arm - .name(name + ".inst.arm") + .name(name() + ".inst.arm") .desc("number of arm instructions executed") ; _quiesce - .name(name + ".inst.quiesce") + .name(name() + ".inst.quiesce") .desc("number of quiesce instructions executed") ; _ivlb - .name(name + ".inst.ivlb") + .name(name() + ".inst.ivlb") .desc("number of ivlb instructions executed") ; _ivle - .name(name + ".inst.ivle") + .name(name() + ".inst.ivle") .desc("number of ivle instructions executed") ; _hwrei - .name(name + ".inst.hwrei") + .name(name() + ".inst.hwrei") .desc("number of hwrei instructions executed") ; _iplCount .init(32) - .name(name + ".ipl_count") + .name(name() + ".ipl_count") .desc("number of times we switched to this ipl") .flags(total | pdf | nozero | nonan) ; _iplGood .init(32) - .name(name + ".ipl_good") + .name(name() + ".ipl_good") .desc("number of times we switched to this ipl from a different ipl") .flags(total | pdf | nozero | nonan) ; _iplTicks .init(32) - .name(name + ".ipl_ticks") + .name(name() + ".ipl_ticks") .desc("number of cycles we spent at this ipl") .flags(total | pdf | nozero | nonan) ; _iplUsed - .name(name + ".ipl_used") + .name(name() + ".ipl_used") .desc("fraction of swpipl calls that actually changed the ipl") .flags(total | nozero | nonan) ; @@ -166,7 +114,7 @@ KSData::regStats(const string &name) _callpal .init(256) - .name(name + ".callpal") + .name(name() + ".callpal") .desc("number of callpals executed") .flags(total | pdf | nozero | nonan) ; @@ -179,7 +127,7 @@ KSData::regStats(const string &name) _syscall .init(SystemCalls::Number) - .name(name + ".syscall") + .name(name() + ".syscall") .desc("number of syscalls executed") .flags(total | pdf | nozero | nonan) ; @@ -193,7 +141,7 @@ KSData::regStats(const string &name) _faults .init(Num_Faults) - .name(name + ".faults") + .name(name() + ".faults") .desc("number of faults") .flags(total | pdf | nozero | nonan) ; @@ -205,85 +153,79 @@ KSData::regStats(const string &name) } _mode - .init(2) - .name(name + ".mode_switch") - .subname(0, "kernel") - .subname(1, "user") + .init(3) + .name(name() + ".mode_switch") .desc("number of protection mode switches") ; + for (int i = 0; i < 3; ++i) + _mode.subname(i, modestr[i]); + _modeGood - .init(2) - .name(name + ".mode_good") + .init(3) + .name(name() + ".mode_good") ; + for (int i = 0; i < 3; ++i) + _modeGood.subname(i, modestr[i]); + _modeFraction - .name(name + ".mode_switch_good") - .subname(0, "kernel") - .subname(1, "user") + .name(name() + ".mode_switch_good") .desc("fraction of useful protection mode switches") .flags(total) ; + + for (int i = 0; i < 3; ++i) + _modeFraction.subname(i, modestr[i]); + _modeFraction = _modeGood / _mode; _modeTicks - .init(2) - .name(name + ".mode_ticks") - .subname(0, "kernel") - .subname(1, "user") + .init(3) + .name(name() + ".mode_ticks") .desc("number of ticks spent at the given mode") .flags(pdf) ; + for (int i = 0; i < 3; ++i) + _modeTicks.subname(i, modestr[i]); _swap_context - .name(name + ".swap_context") + .name(name() + ".swap_context") .desc("number of times the context was actually changed") ; } void -KernelStats::arm() -{ data->_arm++; } - -void -KernelStats::quiesce() -{ data->_quiesce++; } - -void -KernelStats::ivlb() -{ data->_ivlb++; } - -void -KernelStats::ivle() -{ data->_ivle++; } +Statistics::setIdleProcess(Addr idlepcbb) +{ + assert(themode == kernel); + idleProcess = idlepcbb; + themode = idle; + changeMode(themode); +} void -KernelStats::hwrei() -{ data->_hwrei++; } +Statistics::changeMode(cpu_mode newmode) +{ + _mode[newmode]++; -void -KernelStats::fault(Fault fault) -{ data->_faults[fault]++; } + if (newmode == themode) + return; -void -KernelStats::swpipl(int ipl) -{ data->swpipl(ipl); } + DPRINTF(Context, "old mode=%-8s new mode=%-8s\n", + modestr[themode], modestr[newmode]); -void -KernelStats::mode(bool user) -{ data->mode(user); } + _modeGood[newmode]++; + _modeTicks[themode] += curTick - lastModeTick; -void -KernelStats::context(Addr old_pcbb, Addr new_pcbb) -{ data->_swap_context++; } - -void -KernelStats::callpal(int code) -{ data->callpal(code); } + xc->system->kernelBinning->changeMode(newmode); + lastModeTick = curTick; + themode = newmode; +} void -KSData::swpipl(int ipl) +Statistics::swpipl(int ipl) { assert(ipl >= 0 && ipl <= 0x1f && "invalid IPL\n"); @@ -299,30 +241,28 @@ KSData::swpipl(int ipl) } void -KSData::mode(bool user) +Statistics::mode(bool usermode) { - _mode[user]++; - if (user == lastUser) - return; + Addr pcbb = xc->regs.ipr[AlphaISA::IPR_PALtemp23]; - _modeGood[user]++; - _modeTicks[lastUser] += curTick - lastModeTick; + cpu_mode newmode = usermode ? user : kernel; + if (newmode == kernel && pcbb == idleProcess) + newmode = idle; - lastModeTick = curTick; - lastUser = user; - - if (xc->system->bin) { - if (!xc->swCtx || xc->swCtx->callStack.empty()) { - if (user) - xc->system->User->activate(); - else - xc->system->Kernel->activate(); - } - } + changeMode(newmode); +} + +void +Statistics::context(Addr oldpcbb, Addr newpcbb) +{ + assert(themode != user); + + _swap_context++; + changeMode(newpcbb == idleProcess ? idle : kernel); } void -KSData::callpal(int code) +Statistics::callpal(int code) { if (!PAL::name(code)) return; @@ -330,63 +270,34 @@ KSData::callpal(int code) _callpal[code]++; switch (code) { - case PAL::callsys: - { - int number = xc->regs.intRegFile[0]; - if (SystemCalls::validSyscallNumber(number)) { - int cvtnum = SystemCalls::convert(number); - _syscall[cvtnum]++; - } - } + case PAL::callsys: { + int number = xc->regs.intRegFile[0]; + if (SystemCalls::validSyscallNumber(number)) { + int cvtnum = SystemCalls::convert(number); + _syscall[cvtnum]++; + } + } break; + + case PAL::swpctx: + if (xc->system->kernelBinning) + xc->system->kernelBinning->palSwapContext(xc); break; } +} - if (code == PAL::swpctx) { - SWContext *out = xc->swCtx; - System *sys = xc->system; - if (!sys->bin) - return; - DPRINTF(TCPIP, "swpctx event\n"); - if (out) { - DPRINTF(TCPIP, "swapping context out with this stack!\n"); - xc->system->dumpState(xc); - Addr oldPCB = xc->regs.ipr[TheISA::IPR_PALtemp23]; - - if (out->callStack.empty()) { - DPRINTF(TCPIP, "but removing it, cuz empty!\n"); - SWContext *find = sys->findContext(oldPCB); - if (find) { - assert(sys->findContext(oldPCB) == out); - sys->remContext(oldPCB); - } - delete out; - } else { - DPRINTF(TCPIP, "switching out context with pcb %#x, top fn %s\n", - oldPCB, out->callStack.top()->name); - if (!sys->findContext(oldPCB)) { - if (!sys->addContext(oldPCB, out)) - panic("could not add context"); - } - } - } +void +Statistics::serialize(ostream &os) +{ + int exemode = themode; + SERIALIZE_SCALAR(exemode); +} - Addr newPCB = xc->regs.intRegFile[16]; - SWContext *in = sys->findContext(newPCB); - xc->swCtx = in; - - if (in) { - assert(!in->callStack.empty() && - "should not be switching in empty context"); - DPRINTF(TCPIP, "swapping context in with this callstack!\n"); - xc->system->dumpState(xc); - sys->remContext(newPCB); - fnCall *top = in->callStack.top(); - DPRINTF(TCPIP, "switching in to pcb %#x, %s\n", newPCB, top->name); - assert(top->myBin && "should not switch to context with no Bin"); - top->myBin->activate(); - } else { - sys->Kernel->activate(); - } - DPRINTF(TCPIP, "end swpctx\n"); - } +void +Statistics::unserialize(Checkpoint *cp, const string §ion) +{ + int exemode; + UNSERIALIZE_SCALAR(exemode); + themode = (cpu_mode)exemode; } + +/* end namespace Kernel */ } diff --git a/kern/kernel_stats.hh b/kern/kernel_stats.hh index 497403762..8339c578c 100644 --- a/kern/kernel_stats.hh +++ b/kern/kernel_stats.hh @@ -29,35 +29,165 @@ #ifndef __KERNEL_STATS_HH__ #define __KERNEL_STATS_HH__ +#include +#include #include +#include + +#include "base/statistics.hh" +#include "sim/serialize.hh" +#include "targetarch/isa_traits.hh" -class KSData; -class ExecContext; class BaseCPU; +class ExecContext; +class FnEvent; enum Fault; -class KernelStats +namespace Kernel { + +enum cpu_mode { kernel, user, idle, cpu_mode_num }; +extern const char *modestr[]; + +class Binning { private: - KSData *data; + std::string myname; + System *system; + + private: + // lisa's binning stuff + struct fnCall + { + Stats::MainBin *myBin; + std::string name; + }; + + struct SWContext + { + Counter calls; + std::stack callStack; + }; + + std::map fnBins; + std::map swCtxMap; + + std::multimap callerMap; + void populateMap(std::string caller, std::string callee); + + std::vector fnEvents; + + Stats::Scalar<> fnCalls; + + Stats::MainBin *getBin(const std::string &name); + bool findCaller(std::string, std::string) const; + + SWContext *findContext(Addr pcb); + bool addContext(Addr pcb, SWContext *ctx) + { + return (swCtxMap.insert(std::make_pair(pcb, ctx))).second; + } + + void remContext(Addr pcb) + { + swCtxMap.erase(pcb); + } + + void dumpState() const; + + SWContext *swctx; + std::vector binned_fns; + + private: + Stats::MainBin *modeBin[3]; + + public: + const bool bin; + const bool fnbin; + + cpu_mode themode; + void palSwapContext(ExecContext *xc); + void execute(ExecContext *xc, const StaticInstBase *inst); + void call(ExecContext *xc, Stats::MainBin *myBin); + void changeMode(cpu_mode mode); public: - KernelStats(ExecContext *_xc, BaseCPU *_cpu); - ~KernelStats(); + Binning(System *sys); + virtual ~Binning(); + const std::string name() const { return myname; } void regStats(const std::string &name); - void arm(); - void quiesce(); - void ivlb(); - void ivle(); - void hwrei(); + public: + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; - void fault(Fault fault); +class Statistics : public Serializable +{ + friend class Binning; + + private: + std::string myname; + ExecContext *xc; + + Addr idleProcess; + cpu_mode themode; + Tick lastModeTick; + + void changeMode(cpu_mode newmode); + + private: + Stats::Scalar<> _arm; + Stats::Scalar<> _quiesce; + Stats::Scalar<> _ivlb; + Stats::Scalar<> _ivle; + Stats::Scalar<> _hwrei; + + Stats::Vector<> _iplCount; + Stats::Vector<> _iplGood; + Stats::Vector<> _iplTicks; + Stats::Formula _iplUsed; + + Stats::Vector<> _callpal; + Stats::Vector<> _syscall; + Stats::Vector<> _faults; + + Stats::Vector<> _mode; + Stats::Vector<> _modeGood; + Stats::Formula _modeFraction; + Stats::Vector<> _modeTicks; + + Stats::Scalar<> _swap_context; + + private: + int iplLast; + Tick iplLastTick; + + public: + Statistics(ExecContext *context); + + const std::string name() const { return myname; } + void regStats(const std::string &name); + + public: + void arm() { _arm++; } + void quiesce() { _quiesce++; } + void ivlb() { _ivlb++; } + void ivle() { _ivle++; } + void hwrei() { _hwrei++; } + void fault(Fault fault) { _faults[fault]++; } void swpipl(int ipl); - void mode(bool user); - void context(Addr old_pcbb, Addr new_pcbb); + void mode(bool usermode); + void context(Addr oldpcbb, Addr newpcbb); void callpal(int code); + + void setIdleProcess(Addr idle); + + public: + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); }; +/* end namespace Kernel */ } + #endif // __KERNEL_STATS_HH__ diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc index dd188ffe0..10641de87 100644 --- a/kern/linux/linux_system.cc +++ b/kern/linux/linux_system.cc @@ -35,11 +35,6 @@ * up boot time. */ -#include "base/loader/aout_object.hh" -#include "base/loader/elf_object.hh" -#include "base/loader/object_file.hh" -#include "base/loader/symtab.hh" -#include "base/remote_gdb.hh" #include "base/trace.hh" #include "cpu/exec_context.hh" #include "cpu/base_cpu.hh" @@ -58,88 +53,15 @@ extern SymbolTable *debugSymbolTable; using namespace std; -LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, - MemoryController *_memCtrl, PhysicalMemory *_physmem, - const string &kernel_path, const string &console_path, - const string &palcode, const string &boot_osflags, - const bool _bin, const vector &_binned_fns) - : System(_name, _init_param, _memCtrl, _physmem, _bin, _binned_fns), - bin(_bin), binned_fns(_binned_fns) +LinuxSystem::LinuxSystem(Params *p) + : System(p) { - kernelSymtab = new SymbolTable; - consoleSymtab = new SymbolTable; - - /** - * Load the kernel, pal, and console code into memory - */ - // Load kernel code - ObjectFile *kernel = createObjectFile(kernel_path); - if (kernel == NULL) - fatal("Could not load kernel file %s", kernel_path); - - // Load Console Code - ObjectFile *console = createObjectFile(console_path); - if (console == NULL) - fatal("Could not load console file %s", console_path); - - // Load pal file - ObjectFile *pal = createObjectFile(palcode); - if (pal == NULL) - fatal("Could not load PALcode file %s", palcode); - pal->loadSections(physmem, true); - - // Load console file - console->loadSections(physmem, true); - - // Load kernel file - kernel->loadSections(physmem, true); - kernelStart = kernel->textBase(); - kernelEnd = kernel->bssBase() + kernel->bssSize(); - kernelEntry = kernel->entryPoint(); - - // load symbols - if (!kernel->loadGlobalSymbols(kernelSymtab)) - panic("could not load kernel symbols\n"); - debugSymbolTable = kernelSymtab; - - if (!kernel->loadLocalSymbols(kernelSymtab)) - panic("could not load kernel local symbols\n"); - - if (!console->loadGlobalSymbols(consoleSymtab)) - panic("could not load console symbols\n"); - - DPRINTF(Loader, "Kernel start = %#x\n" - "Kernel end = %#x\n" - "Kernel entry = %#x\n", - kernelStart, kernelEnd, kernelEntry); - - DPRINTF(Loader, "Kernel loaded...\n"); - - -#ifdef DEBUG - kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); - consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic"); -#endif - - skipIdeDelay50msEvent = new SkipFuncEvent(&pcEventQueue, - "ide_delay_50ms"); - - skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue, - "calibrate_delay"); - - skipCacheProbeEvent = new SkipFuncEvent(&pcEventQueue, - "determine_cpu_caches"); - - debugPrintkEvent = new DebugPrintkEvent(&pcEventQueue, "dprintk"); - - printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo"); - Addr addr = 0; /** - * find the address of the est_cycle_freq variable and insert it so we don't - * through the lengthly process of trying to calculated it by using the PIT, - * RTC, etc. + * find the address of the est_cycle_freq variable and insert it + * so we don't through the lengthly process of trying to + * calculated it by using the PIT, RTC, etc. */ if (kernelSymtab->findAddress("est_cycle_freq", addr)) { Addr paddr = vtophys(physmem, addr); @@ -151,19 +73,6 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, } - /** - * Copy the osflags (kernel arguments) into the consoles memory. Presently - * Linux does use the console service routine to get these command line - * arguments, but we might as well make them available just in case. - */ - if (consoleSymtab->findAddress("env_booted_osflags", addr)) { - Addr paddr = vtophys(physmem, addr); - char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); - - if (osflags) - strcpy(osflags, boot_osflags.c_str()); - } - /** * Since we aren't using a bootloader, we have to copy the kernel arguments * directly into the kernels memory. @@ -172,31 +81,10 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, Addr paddr = vtophys(physmem, PARAM_ADDR); char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t)); if (commandline) - strcpy(commandline, boot_osflags.c_str()); + strcpy(commandline, params->boot_osflags.c_str()); } - /** - * Set the hardware reset parameter block system type and revision - * information to Tsunami. - */ - if (consoleSymtab->findAddress("xxm_rpb", addr)) { - Addr paddr = vtophys(physmem, addr); - char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (hwprb) { - // Tsunami - *(uint64_t*)(hwprb + 0x50) = htoa(ULL(34)); - - // Plain DP264 - *(uint64_t*)(hwprb + 0x58) = htoa(ULL(1) << 10); - } - else - panic("could not translate hwprb addr to set system type/variation\n"); - - } else - panic("could not find hwprb to set system type/variation\n"); - /** * EV5 only supports 127 ASNs so we are going to tell the kernel that the * paritiuclar EV6 we have only supports 127 asns. @@ -210,59 +98,63 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, if (dp264_mv) { *(uint32_t*)(dp264_mv+0x18) = htoa((uint32_t)127); } else - panic("could not translate dp264_mv addr to set the MAX_ASN to 127\n"); + panic("could not translate dp264_mv addr\n"); } else - panic("could not find dp264_mv to set the MAX_ASN to 127\n"); - - + panic("could not find dp264_mv\n"); #ifdef DEBUG + kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); if (kernelSymtab->findAddress("panic", addr)) kernelPanicEvent->schedule(addr); else panic("could not find kernel symbol \'panic\'"); - - if (consoleSymtab->findAddress("panic", addr)) - consolePanicEvent->schedule(addr); #endif /** - * Any time ide_delay_50ms, calibarte_delay or determine_cpu_caches is called - * just skip the function. Currently determine_cpu_caches only is used put - * information in proc, however if that changes in the future we will have to - * fill in the cache size variables appropriately. + * Any time ide_delay_50ms, calibarte_delay or + * determine_cpu_caches is called just skip the + * function. Currently determine_cpu_caches only is used put + * information in proc, however if that changes in the future we + * will have to fill in the cache size variables appropriately. */ + skipIdeDelay50msEvent = new SkipFuncEvent(&pcEventQueue, "ide_delay_50ms"); if (kernelSymtab->findAddress("ide_delay_50ms", addr)) skipIdeDelay50msEvent->schedule(addr+sizeof(MachInst)); + skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue, + "calibrate_delay"); if (kernelSymtab->findAddress("calibrate_delay", addr)) skipDelayLoopEvent->schedule(addr+sizeof(MachInst)); + skipCacheProbeEvent = new SkipFuncEvent(&pcEventQueue, + "determine_cpu_caches"); if (kernelSymtab->findAddress("determine_cpu_caches", addr)) skipCacheProbeEvent->schedule(addr+sizeof(MachInst)); + debugPrintkEvent = new DebugPrintkEvent(&pcEventQueue, "dprintk"); if (kernelSymtab->findAddress("dprintk", addr)) - debugPrintkEvent->schedule(addr+sizeof(MachInst)*2); + debugPrintkEvent->schedule(addr+8); + + idleStartEvent = new IdleStartEvent(&pcEventQueue, "cpu_idle", this); + if (kernelSymtab->findAddress("cpu_idle", addr)) + idleStartEvent->schedule(addr); - if (kernelSymtab->findAddress("alpha_switch_to", addr) && - DTRACE(Thread)) - printThreadEvent->schedule(addr+sizeof(MachInst)*6); + printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo"); + if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread)) + printThreadEvent->schedule(addr + sizeof(MachInst) * 6); } LinuxSystem::~LinuxSystem() { - delete kernel; - delete console; - - delete kernelSymtab; - delete consoleSymtab; - +#ifdef DEBUG delete kernelPanicEvent; - delete consolePanicEvent; +#endif delete skipIdeDelay50msEvent; delete skipDelayLoopEvent; delete skipCacheProbeEvent; + delete debugPrintkEvent; + delete idleStartEvent; } @@ -283,92 +175,64 @@ LinuxSystem::setDelayLoop(ExecContext *xc) } } -int -LinuxSystem::registerExecContext(ExecContext *xc) -{ - int xcIndex = System::registerExecContext(xc); - - if (xcIndex == 0) { - // activate with zero delay so that we start ticking right - // away on cycle 0 - xc->activate(0); - } - - RemoteGDB *rgdb = new RemoteGDB(this, xc); - GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex); - gdbl->listen(); - /** - * Uncommenting this line waits for a remote debugger to connect - * to the simulator before continuing. - */ - //gdbl->accept(); - - if (remoteGDB.size() <= xcIndex) { - remoteGDB.resize(xcIndex+1); - } - - remoteGDB[xcIndex] = rgdb; - - return xcIndex; -} - - -void -LinuxSystem::replaceExecContext(ExecContext *xc, int xcIndex) -{ - System::replaceExecContext(xcIndex, xc); - remoteGDB[xcIndex]->replaceExecContext(xc); -} - -bool -LinuxSystem::breakpoint() -{ - return remoteGDB[0]->trap(ALPHA_KENTRY_IF); -} - BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) - Param bin; SimObjectParam mem_ctl; SimObjectParam physmem; - Param init_param; Param kernel_code; Param console_code; Param pal_code; - Param boot_osflags; - VectorParam binned_fns; + Param boot_osflags; Param readfile; + Param init_param; + + Param system_type; + Param system_rev; + + Param bin; + VectorParam binned_fns; END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem) - - INIT_PARAM_DFLT(bin, "is this system to be binned", false), INIT_PARAM(mem_ctl, "memory controller"), INIT_PARAM(physmem, "phsyical memory"), - INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), - INIT_PARAM(kernel_code, "file that contains the code"), + INIT_PARAM(kernel_code, "file that contains the kernel code"), INIT_PARAM(console_code, "file that contains the console code"), INIT_PARAM(pal_code, "file that contains palcode"), INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", - "a"), - INIT_PARAM(binned_fns, "functions to be broken down and binned"), - INIT_PARAM_DFLT(readfile, "file to read startup script from", "") - + "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(bin, "is this system to be binned", false), + INIT_PARAM(binned_fns, "functions to be broken down and binned") END_INIT_SIM_OBJECT_PARAMS(LinuxSystem) CREATE_SIM_OBJECT(LinuxSystem) { - LinuxSystem *sys = new LinuxSystem(getInstanceName(), init_param, mem_ctl, - physmem, kernel_code, console_code, - pal_code, boot_osflags, bin, binned_fns); - - sys->readfile = readfile; - return sys; + System::Params *p = new System::Params; + p->name = getInstanceName(); + p->memctrl = mem_ctl; + p->physmem = physmem; + p->kernel_path = kernel_code; + p->console_path = console_code; + p->palcode = pal_code; + p->boot_osflags = boot_osflags; + p->init_param = init_param; + p->readfile = readfile; + p->system_type = system_type; + p->system_rev = system_rev; + p->bin = bin; + p->binned_fns = binned_fns; + + return new LinuxSystem(p); } REGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem) + diff --git a/kern/linux/linux_system.hh b/kern/linux/linux_system.hh index fbfcb788f..707204607 100644 --- a/kern/linux/linux_system.hh +++ b/kern/linux/linux_system.hh @@ -26,32 +26,27 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __LINUX_SYSTEM_HH__ -#define __LINUX_SYSTEM_HH__ +#ifndef __KERN_LINUX_LINUX_SYSTEM_HH__ +#define __KERN_LINUX_LINUX_SYSTEM_HH__ -#include - -#include "sim/system.hh" #include "sim/host.hh" +#include "sim/system.hh" #include "targetarch/isa_traits.hh" -#include - /** * MAGIC address where the kernel arguments should go. Defined as * PARAM in linux kernel alpha-asm. */ -const Addr PARAM_ADDR = ULL(0xfffffc000030a000); +const Addr PARAM_ADDR = ULL(0xfffffc000030a000); class ExecContext; -class ElfObject; -class SymbolTable; + +class BreakPCEvent; class DebugPrintkEvent; class BreakPCEvent; class LinuxSkipDelayLoopEvent; class SkipFuncEvent; -class FnEvent; -class AlphaArguments; +class IdleStartEvent; class PrintThreadInfo; /** @@ -62,96 +57,42 @@ class PrintThreadInfo; class LinuxSystem : public System { private: - /** Object pointer for the kernel code */ - ElfObject *kernel; - - /** Object pointer for the console code */ - ElfObject *console; - - /** kernel Symbol table */ - SymbolTable *kernelSymtab; - - /** console symbol table */ - SymbolTable *consoleSymtab; - +#ifdef DEBUG /** Event to halt the simulator if the kernel calls panic() */ BreakPCEvent *kernelPanicEvent; +#endif - /** Event to halt the simulator if the console calls panic() */ - BreakPCEvent *consolePanicEvent; - - /** Event to skip determine_cpu_caches() because we don't support the - * IPRs that the code can access to figure out cache sizes + /** + * Event to skip determine_cpu_caches() because we don't support + * the IPRs that the code can access to figure out cache sizes */ SkipFuncEvent *skipCacheProbeEvent; /** PC based event to skip the ide_delay_50ms() call */ SkipFuncEvent *skipIdeDelay50msEvent; - /** PC based event to skip the dprink() call and emulate its functionality */ + /** + * PC based event to skip the dprink() call and emulate its + * functionality + */ DebugPrintkEvent *debugPrintkEvent; - /** Skip calculate_delay_loop() rather than waiting for this to be + /** + * Skip calculate_delay_loop() rather than waiting for this to be * calculated */ LinuxSkipDelayLoopEvent *skipDelayLoopEvent; PrintThreadInfo *printThreadEvent; - /** Begining of kernel code */ - Addr kernelStart; - - /** End of kernel code */ - Addr kernelEnd; - - /** Entry point in the kernel to start at */ - Addr kernelEntry; - - bool bin; - std::vector binned_fns; + /** Grab the PCBB of the idle process when it starts */ + IdleStartEvent *idleStartEvent; public: - std::vector remoteGDB; - std::vector gdbListen; - - LinuxSystem(const std::string _name, - const uint64_t _init_param, - MemoryController *_memCtrl, - PhysicalMemory *_physmem, - const std::string &kernel_path, - const std::string &console_path, - const std::string &palcode, - const std::string &boot_osflags, - const bool _bin, - const std::vector &_binned_fns); - + LinuxSystem(Params *p); ~LinuxSystem(); void setDelayLoop(ExecContext *xc); - - int registerExecContext(ExecContext *xc); - void replaceExecContext(ExecContext *xc, int xcIndex); - - /** - * Returns the addess the kernel starts at. - * @return address the kernel starts at - */ - Addr getKernelStart() const { return kernelStart; } - - /** - * Returns the addess the kernel ends at. - * @return address the kernel ends at - */ - Addr getKernelEnd() const { return kernelEnd; } - - /** - * Returns the addess the entry point to the kernel code. - * @return entry point of the kernel code - */ - Addr getKernelEntry() const { return kernelEntry; } - - - bool breakpoint(); }; -#endif // __LINUX_SYSTEM_HH__ +#endif // __KERN_LINUX_LINUX_SYSTEM_HH__ diff --git a/kern/system_events.cc b/kern/system_events.cc index 351c3ddb2..91daf53ca 100644 --- a/kern/system_events.cc +++ b/kern/system_events.cc @@ -30,9 +30,9 @@ #include "cpu/base_cpu.hh" #include "cpu/full_cpu/bpred.hh" #include "cpu/full_cpu/full_cpu.hh" +#include "kern/kernel_stats.hh" #include "kern/system_events.hh" #include "sim/system.hh" -#include "sim/sw_context.hh" void SkipFuncEvent::process(ExecContext *xc) @@ -52,11 +52,9 @@ SkipFuncEvent::process(ExecContext *xc) } -FnEvent::FnEvent(PCEventQueue *q, const std::string & desc, System *system) - : PCEvent(q, desc), _name(desc) +FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Stats::MainBin *bin) + : PCEvent(q, desc), _name(desc), mybin(bin) { - myBin = system->getBin(desc); - assert(myBin); } void @@ -64,46 +62,12 @@ FnEvent::process(ExecContext *xc) { if (xc->misspeculating()) return; - assert(xc->system->bin && "FnEvent must be in a binned system"); - SWContext *ctx = xc->swCtx; - DPRINTF(TCPIP, "%s: %s Event!!!\n", xc->system->name(), description); - if (ctx && !ctx->callStack.empty()) { - DPRINTF(TCPIP, "already a callstack!\n"); - fnCall *last = ctx->callStack.top(); - - if (last->name == "idle_thread") - ctx->calls++; - - if (!xc->system->findCaller(myname(), "" ) && - !xc->system->findCaller(myname(), last->name)) { - - DPRINTF(TCPIP, "but can't find parent %s\n", last->name); - return; - } - ctx->calls--; + xc->system->kernelBinning->call(xc, mybin); +} - //assert(!ctx->calls && "on a binned fn, calls should == 0 (but can happen in boot)"); - } else { - DPRINTF(TCPIP, "no callstack yet\n"); - if (!xc->system->findCaller(myname(), "")) { - DPRINTF(TCPIP, "not the right function, returning\n"); - return; - } - if (!ctx) { - DPRINTF(TCPIP, "creating new context for %s\n", myname()); - ctx = new SWContext; - xc->swCtx = ctx; - } - } - DPRINTF(TCPIP, "adding fn %s to context\n", myname()); - fnCall *call = new fnCall; - call->myBin = myBin; - call->name = myname(); - ctx->callStack.push(call); - myBin->activate(); - xc->system->fnCalls++; - DPRINTF(TCPIP, "fnCalls for %s is %d\n", description, - xc->system->fnCalls.value()); - xc->system->dumpState(xc); +void +IdleStartEvent::process(ExecContext *xc) +{ + xc->kernelStats->setIdleProcess(xc->regs.ipr[AlphaISA::IPR_PALtemp23]); } diff --git a/kern/system_events.hh b/kern/system_events.hh index 7f658bde9..95027572f 100644 --- a/kern/system_events.hh +++ b/kern/system_events.hh @@ -44,13 +44,24 @@ class SkipFuncEvent : public PCEvent class FnEvent : public PCEvent { public: - FnEvent(PCEventQueue *q, const std::string &desc, System *system); + FnEvent(PCEventQueue *q, const std::string &desc, Stats::MainBin *bin); virtual void process(ExecContext *xc); std::string myname() const { return _name; } private: std::string _name; - Stats::MainBin *myBin; + Stats::MainBin *mybin; }; +class IdleStartEvent : public PCEvent +{ + private: + System *system; + + public: + IdleStartEvent(PCEventQueue *q, const std::string &desc, System *sys) + : PCEvent(q, desc), system(sys) + {} + virtual void process(ExecContext *xc); +}; #endif // __SYSTEM_EVENTS_HH__ diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc index e96cc9c5d..fb9d43a0e 100644 --- a/kern/tru64/tru64_events.cc +++ b/kern/tru64/tru64_events.cc @@ -47,7 +47,7 @@ BadAddrEvent::process(ExecContext *xc) uint64_t a0 = xc->regs.intRegFile[ArgumentReg0]; if (a0 < ALPHA_K0SEG_BASE || a0 >= ALPHA_K1SEG_BASE || - xc->memCtrl->badaddr(ALPHA_K0SEG_TO_PHYS(a0) & PA_IMPL_MASK)) { + xc->memctrl->badaddr(ALPHA_K0SEG_TO_PHYS(a0) & PA_IMPL_MASK)) { DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0); xc->regs.intRegFile[ReturnValueReg] = 0x1; diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc index 4395162e4..5493139ee 100644 --- a/kern/tru64/tru64_system.cc +++ b/kern/tru64/tru64_system.cc @@ -26,11 +26,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "base/loader/aout_object.hh" -#include "base/loader/ecoff_object.hh" -#include "base/loader/object_file.hh" -#include "base/loader/symtab.hh" -#include "base/remote_gdb.hh" #include "base/trace.hh" #include "cpu/exec_context.hh" #include "kern/tru64/tru64_events.hh" @@ -42,75 +37,11 @@ #include "targetarch/isa_traits.hh" #include "targetarch/vtophys.hh" -extern SymbolTable *debugSymbolTable; - using namespace std; -Tru64System::Tru64System(const string _name, const uint64_t _init_param, - MemoryController *_memCtrl, PhysicalMemory *_physmem, - const string &kernel_path, const string &console_path, - const string &palcode, const string &boot_osflags, - const bool _bin, const vector &_binned_fns, - const uint64_t system_type, const uint64_t system_rev) - : System(_name, _init_param, _memCtrl, _physmem, _bin,_binned_fns), - bin(_bin), binned_fns(_binned_fns) +Tru64System::Tru64System(Tru64System::Params *p) + : System(p) { - kernelSymtab = new SymbolTable; - consoleSymtab = new SymbolTable; - debugSymbolTable = kernelSymtab; - - ObjectFile *kernel = createObjectFile(kernel_path); - if (kernel == NULL) - fatal("Could not load kernel file %s", kernel_path); - - ObjectFile *console = createObjectFile(console_path); - if (console == NULL) - fatal("Could not load console file %s", console_path); - - if (!kernel->loadGlobalSymbols(kernelSymtab)) - panic("could not load kernel symbols\n"); - - if (!console->loadGlobalSymbols(consoleSymtab)) - panic("could not load console symbols\n"); - - // Load pal file - ObjectFile *pal = createObjectFile(palcode); - if (pal == NULL) - fatal("Could not load PALcode file %s", palcode); - pal->loadSections(physmem, true); - - // Load console file - console->loadSections(physmem, true); - - // Load kernel file - kernel->loadSections(physmem, true); - kernelStart = kernel->textBase(); - kernelEnd = kernel->bssBase() + kernel->bssSize(); - kernelEntry = kernel->entryPoint(); - - DPRINTF(Loader, "Kernel start = %#x\n" - "Kernel end = %#x\n" - "Kernel entry = %#x\n", - kernelStart, kernelEnd, kernelEntry); - - DPRINTF(Loader, "Kernel loaded...\n"); - -#ifdef DEBUG - kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); - consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic"); -#endif - badaddrEvent = new BadAddrEvent(&pcEventQueue, "badaddr"); - skipPowerStateEvent = new SkipFuncEvent(&pcEventQueue, - "tl_v48_capture_power_state"); - skipScavengeBootEvent = new SkipFuncEvent(&pcEventQueue, - "pmap_scavenge_boot"); - printfEvent = new PrintfEvent(&pcEventQueue, "printf"); - debugPrintfEvent = new DebugPrintfEvent(&pcEventQueue, - "debug_printf", false); - debugPrintfrEvent = new DebugPrintfEvent(&pcEventQueue, - "debug_printfr", true); - dumpMbufEvent = new DumpMbufEvent(&pcEventQueue, "dump_mbuf"); - Addr addr = 0; if (kernelSymtab->findAddress("enable_async_printf", addr)) { Addr paddr = vtophys(physmem, addr); @@ -121,180 +52,124 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param, *(uint32_t *)enable_async_printf = 0; } - if (consoleSymtab->findAddress("env_booted_osflags", addr)) { - Addr paddr = vtophys(physmem, addr); - char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); - - if (osflags) - strcpy(osflags, boot_osflags.c_str()); - } - - if (consoleSymtab->findAddress("xxm_rpb", addr)) { - Addr paddr = vtophys(physmem, addr); - char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (hwprb) { - *(uint64_t*)(hwprb+0x50) = system_type; - *(uint64_t*)(hwprb+0x58) = system_rev; - } - else - panic("could not translate hwprb addr to set system type/variation\n"); - } else - panic("could not find hwprb to set system type/variation\n"); - - #ifdef DEBUG + kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); if (kernelSymtab->findAddress("panic", addr)) kernelPanicEvent->schedule(addr); else panic("could not find kernel symbol \'panic\'"); - - if (consoleSymtab->findAddress("panic", addr)) - consolePanicEvent->schedule(addr); #endif + badaddrEvent = new BadAddrEvent(&pcEventQueue, "badaddr"); if (kernelSymtab->findAddress("badaddr", addr)) badaddrEvent->schedule(addr); else panic("could not find kernel symbol \'badaddr\'"); + skipPowerStateEvent = new SkipFuncEvent(&pcEventQueue, + "tl_v48_capture_power_state"); if (kernelSymtab->findAddress("tl_v48_capture_power_state", addr)) skipPowerStateEvent->schedule(addr); + skipScavengeBootEvent = new SkipFuncEvent(&pcEventQueue, + "pmap_scavenge_boot"); if (kernelSymtab->findAddress("pmap_scavenge_boot", addr)) skipScavengeBootEvent->schedule(addr); #if TRACING_ON + printfEvent = new PrintfEvent(&pcEventQueue, "printf"); if (kernelSymtab->findAddress("printf", addr)) printfEvent->schedule(addr); + debugPrintfEvent = new DebugPrintfEvent(&pcEventQueue, "debug_printf", + false); if (kernelSymtab->findAddress("m5printf", addr)) debugPrintfEvent->schedule(addr); + debugPrintfrEvent = new DebugPrintfEvent(&pcEventQueue, "debug_printfr", + true); if (kernelSymtab->findAddress("m5printfr", addr)) debugPrintfrEvent->schedule(addr); + dumpMbufEvent = new DumpMbufEvent(&pcEventQueue, "dump_mbuf"); if (kernelSymtab->findAddress("m5_dump_mbuf", addr)) dumpMbufEvent->schedule(addr); #endif - - // BINNING STUFF - if (bin == true) { - int end = binned_fns.size(); - Addr address = 0; - - for (int i = 0; i < end; i +=2) { - if (kernelSymtab->findAddress(binned_fns[i], address)) - fnEvents[(i>>1)]->schedule(address); - else - panic("could not find kernel symbol %s\n", binned_fns[i]); - } - } - // } Tru64System::~Tru64System() { - delete kernel; - delete console; - - delete kernelSymtab; - delete consoleSymtab; - #ifdef DEBUG delete kernelPanicEvent; - delete consolePanicEvent; #endif delete badaddrEvent; delete skipPowerStateEvent; delete skipScavengeBootEvent; +#if TRACING_ON delete printfEvent; delete debugPrintfEvent; delete debugPrintfrEvent; delete dumpMbufEvent; -} - -int -Tru64System::registerExecContext(ExecContext *xc) -{ - int xcIndex = System::registerExecContext(xc); - - if (xcIndex == 0) { - // activate with zero delay so that we start ticking right - // away on cycle 0 - xc->activate(0); - } - - RemoteGDB *rgdb = new RemoteGDB(this, xc); - GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex); - gdbl->listen(); - - if (remoteGDB.size() <= xcIndex) { - remoteGDB.resize(xcIndex+1); - } - - remoteGDB[xcIndex] = rgdb; - - return xcIndex; -} - - -void -Tru64System::replaceExecContext(ExecContext *xc, int xcIndex) -{ - System::replaceExecContext(xcIndex, xc); - remoteGDB[xcIndex]->replaceExecContext(xc); -} - -bool -Tru64System::breakpoint() -{ - return remoteGDB[0]->trap(ALPHA_KENTRY_INT); +#endif } BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System) - Param bin; SimObjectParam mem_ctl; SimObjectParam physmem; - Param init_param; Param kernel_code; Param console_code; Param pal_code; + Param boot_osflags; - VectorParam binned_fns; + Param readfile; + Param init_param; + Param system_type; Param system_rev; + Param bin; + VectorParam binned_fns; + END_DECLARE_SIM_OBJECT_PARAMS(Tru64System) BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64System) - INIT_PARAM_DFLT(bin, "is this system to be binned", false), INIT_PARAM(mem_ctl, "memory controller"), INIT_PARAM(physmem, "phsyical memory"), - INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), INIT_PARAM(kernel_code, "file that contains the kernel code"), INIT_PARAM(console_code, "file that contains the console code"), INIT_PARAM(pal_code, "file that contains palcode"), INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", "a"), - INIT_PARAM(binned_fns, "functions to be broken down and binned"), + 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", 12), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1) - + INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1), + INIT_PARAM_DFLT(bin, "is this system to be binned", false), + INIT_PARAM(binned_fns, "functions to be broken down and binned") END_INIT_SIM_OBJECT_PARAMS(Tru64System) CREATE_SIM_OBJECT(Tru64System) { - Tru64System *sys = new Tru64System(getInstanceName(), init_param, mem_ctl, - physmem, kernel_code, console_code, - pal_code, boot_osflags, bin, - binned_fns, system_type, system_rev); - - return sys; + System::Params *p = new System::Params; + p->name = getInstanceName(); + p->memctrl = mem_ctl; + p->physmem = physmem; + p->kernel_path = kernel_code; + p->console_path = console_code; + p->palcode = pal_code; + p->boot_osflags = boot_osflags; + p->init_param = init_param; + p->readfile = readfile; + p->system_type = system_type; + p->system_rev = system_rev; + p->bin = bin; + p->binned_fns = binned_fns; + + return new Tru64System(p); } REGISTER_SIM_OBJECT("Tru64System", Tru64System) diff --git a/kern/tru64/tru64_system.hh b/kern/tru64/tru64_system.hh index 8dd696b79..13d283fb3 100644 --- a/kern/tru64/tru64_system.hh +++ b/kern/tru64/tru64_system.hh @@ -26,18 +26,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __TRU64_SYSTEM_HH__ -#define __TRU64_SYSTEM_HH__ - -#include -#include +#ifndef __KERN_TRU64_TRU64_SYSTEM_HH__ +#define __KERN_TRU64_TRU64_SYSTEM_HH__ #include "sim/system.hh" #include "targetarch/isa_traits.hh" class ExecContext; -class EcoffObject; -class SymbolTable; class BreakPCEvent; class BadAddrEvent; @@ -45,20 +40,16 @@ class SkipFuncEvent; class PrintfEvent; class DebugPrintfEvent; class DumpMbufEvent; -class FnEvent; class AlphaArguments; class Tru64System : public System { private: - EcoffObject *kernel; - EcoffObject *console; - - SymbolTable *kernelSymtab; - SymbolTable *consoleSymtab; - +#ifdef DEBUG + /** Event to halt the simulator if the kernel calls panic() */ BreakPCEvent *kernelPanicEvent; - BreakPCEvent *consolePanicEvent; +#endif + BadAddrEvent *badaddrEvent; SkipFuncEvent *skipPowerStateEvent; SkipFuncEvent *skipScavengeBootEvent; @@ -67,43 +58,12 @@ class Tru64System : public System DebugPrintfEvent *debugPrintfrEvent; DumpMbufEvent *dumpMbufEvent; - private: - - Addr kernelStart; - Addr kernelEnd; - Addr kernelEntry; - bool bin; - std::vector binned_fns; - - public: - std::vector remoteGDB; - std::vector gdbListen; - public: - Tru64System(const std::string _name, - const uint64_t _init_param, - MemoryController *_memCtrl, - PhysicalMemory *_physmem, - const std::string &kernel_path, - const std::string &console_path, - const std::string &palcode, - const std::string &boot_osflags, - const bool _bin, - const std::vector &binned_fns, - const uint64_t system_type, - const uint64_t system_rev); + Tru64System(Params *p); ~Tru64System(); - int registerExecContext(ExecContext *xc); - void replaceExecContext(ExecContext *xc, int xcIndex); - - Addr getKernelStart() const { return kernelStart; } - Addr getKernelEnd() const { return kernelEnd; } - Addr getKernelEntry() const { return kernelEntry; } - bool breakpoint(); - static void Printf(AlphaArguments args); static void DumpMbuf(AlphaArguments args); }; -#endif // __TRU64_SYSTEM_HH__ +#endif // __KERN_TRU64_TRU64_SYSTEM_HH__ diff --git a/sim/process.cc b/sim/process.cc index 7f93c1d9e..b4febc75b 100644 --- a/sim/process.cc +++ b/sim/process.cc @@ -161,7 +161,7 @@ Process::registerExecContext(ExecContext *xc) void -Process::replaceExecContext(int xcIndex, ExecContext *xc) +Process::replaceExecContext(ExecContext *xc, int xcIndex) { if (xcIndex >= execContexts.size()) { panic("replaceExecContext: bad xcIndex, %d >= %d\n", diff --git a/sim/process.hh b/sim/process.hh index bd6adc55c..bb4829875 100644 --- a/sim/process.hh +++ b/sim/process.hh @@ -130,7 +130,7 @@ class Process : public SimObject int registerExecContext(ExecContext *xc); - void replaceExecContext(int xcIndex, ExecContext *xc); + void replaceExecContext(ExecContext *xc, int xcIndex); // map simulator fd sim_fd to target fd tgt_fd void dup_fd(int sim_fd, int tgt_fd); diff --git a/sim/system.cc b/sim/system.cc index b5a0e7a56..2d91e187b 100644 --- a/sim/system.cc +++ b/sim/system.cc @@ -26,7 +26,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "base/loader/object_file.hh" +#include "base/loader/symtab.hh" +#include "base/remote_gdb.hh" #include "cpu/exec_context.hh" +#include "kern/kernel_stats.hh" +#include "mem/functional_mem/memory_control.hh" +#include "mem/functional_mem/physical_memory.hh" #include "targetarch/vtophys.hh" #include "sim/param.hh" #include "sim/system.hh" @@ -38,82 +44,160 @@ vector System::systemList; int System::numSystemsRunning = 0; -System::System(const std::string _name, - const uint64_t _init_param, - MemoryController *_memCtrl, - PhysicalMemory *_physmem, - const bool _bin, - const std::vector &binned_fns) - - : SimObject(_name), - init_param(_init_param), - memCtrl(_memCtrl), - physmem(_physmem), - bin(_bin), - binned_fns(binned_fns) -{ - // increment the number of running systems - numSystemsRunning++; +extern SymbolTable *debugSymbolTable; +System::System(Params *p) + : SimObject(p->name), memctrl(p->memctrl), physmem(p->physmem), + init_param(p->init_param), params(p) +{ // add self to global system list systemList.push_back(this); - if (bin == true) { - Kernel = new Stats::MainBin("non TCPIP Kernel stats"); - Kernel->activate(); - User = new Stats::MainBin("User stats"); - - int end = binned_fns.size(); - assert(!(end & 1)); - Stats::MainBin *Bin; - - fnEvents.resize(end>>1); + kernelSymtab = new SymbolTable; + consoleSymtab = new SymbolTable; + debugSymbolTable = kernelSymtab; + + /** + * Load the kernel, pal, and console code into memory + */ + // Load kernel code + kernel = createObjectFile(params->kernel_path); + if (kernel == NULL) + fatal("Could not load kernel file %s", params->kernel_path); + + // Load Console Code + console = createObjectFile(params->console_path); + if (console == NULL) + fatal("Could not load console file %s", params->console_path); + + // Load pal file + pal = createObjectFile(params->palcode); + if (pal == NULL) + fatal("Could not load PALcode file %s", params->palcode); + + + // Load program sections into memory + pal->loadSections(physmem, true); + console->loadSections(physmem, true); + kernel->loadSections(physmem, true); + + // setup entry points + kernelStart = kernel->textBase(); + kernelEnd = kernel->bssBase() + kernel->bssSize(); + kernelEntry = kernel->entryPoint(); + + // load symbols + if (!kernel->loadGlobalSymbols(kernelSymtab)) + panic("could not load kernel symbols\n"); + debugSymbolTable = kernelSymtab; + + if (!kernel->loadLocalSymbols(kernelSymtab)) + panic("could not load kernel local symbols\n"); + + if (!console->loadGlobalSymbols(consoleSymtab)) + panic("could not load console symbols\n"); + + DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); + DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); + DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); + DPRINTF(Loader, "Kernel loaded...\n"); + + Addr addr = 0; +#ifdef DEBUG + consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic"); + if (consoleSymtab->findAddress("panic", addr)) + consolePanicEvent->schedule(addr); +#endif + + /** + * Copy the osflags (kernel arguments) into the consoles + * memory. (Presently Linux does not use the console service + * routine to get these command line arguments, but Tru64 and + * others do.) + */ + if (consoleSymtab->findAddress("env_booted_osflags", addr)) { + Addr paddr = vtophys(physmem, addr); + char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); + + if (osflags) + strcpy(osflags, params->boot_osflags.c_str()); + } - for (int i = 0; i < end; i +=2) { - Bin = new Stats::MainBin(binned_fns[i]); - fnBins.insert(make_pair(binned_fns[i], Bin)); + /** + * Set the hardware reset parameter block system type and revision + * information to Tsunami. + */ + if (consoleSymtab->findAddress("xxm_rpb", addr)) { + Addr paddr = vtophys(physmem, addr); + char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); - fnEvents[(i>>1)] = new FnEvent(&pcEventQueue, binned_fns[i], this); + if (!hwrpb) + panic("could not translate hwrpb addr\n"); - if (binned_fns[i+1] == "null") - populateMap(binned_fns[i], ""); - else - populateMap(binned_fns[i], binned_fns[i+1]); - } + *(uint64_t*)(hwrpb+0x50) = params->system_type; + *(uint64_t*)(hwrpb+0x58) = params->system_rev; + } else + panic("could not find hwrpb\n"); - fnCalls - .name(name() + ":fnCalls") - .desc("all fn calls being tracked") - ; + // increment the number of running systms + numSystemsRunning++; - } else - Kernel = NULL; + kernelBinning = new Kernel::Binning(this); } - System::~System() { - if (bin == true) { - int end = fnEvents.size(); - for (int i = 0; i < end; ++i) { - delete fnEvents[i]; - } - fnEvents.clear(); - } + delete kernelSymtab; + delete consoleSymtab; + delete kernel; + delete console; + delete pal; + + delete kernelBinning; + +#ifdef DEBUG + delete consolePanicEvent; +#endif } +bool +System::breakpoint() +{ + return remoteGDB[0]->trap(ALPHA_KENTRY_INT); +} int System::registerExecContext(ExecContext *xc) { - int myIndex = execContexts.size(); + int xcIndex = execContexts.size(); execContexts.push_back(xc); - return myIndex; -} + if (xcIndex == 0) { + // activate with zero delay so that we start ticking right + // away on cycle 0 + xc->activate(0); + } + + RemoteGDB *rgdb = new RemoteGDB(this, xc); + GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex); + gdbl->listen(); + /** + * Uncommenting this line waits for a remote debugger to connect + * to the simulator before continuing. + */ + //gdbl->accept(); + + if (remoteGDB.size() <= xcIndex) { + remoteGDB.resize(xcIndex+1); + } + + remoteGDB[xcIndex] = rgdb; + + return xcIndex; +} void -System::replaceExecContext(int xcIndex, ExecContext *xc) +System::replaceExecContext(ExecContext *xc, int xcIndex) { if (xcIndex >= execContexts.size()) { panic("replaceExecContext: bad xcIndex, %d >= %d\n", @@ -121,154 +205,44 @@ System::replaceExecContext(int xcIndex, ExecContext *xc) } execContexts[xcIndex] = xc; + remoteGDB[xcIndex]->replaceExecContext(xc); } - -void -System::printSystems() -{ - vector::iterator i = systemList.begin(); - vector::iterator end = systemList.end(); - for (; i != end; ++i) { - System *sys = *i; - cerr << "System " << sys->name() << ": " << hex << sys << endl; - } -} - -extern "C" void -printSystems() +System::regStats() { - System::printSystems(); + kernelBinning->regStats(name() + ".kern"); } void -System::populateMap(std::string callee, std::string caller) +System::serialize(ostream &os) { - multimap::const_iterator i; - i = callerMap.insert(make_pair(callee, caller)); - assert(i != callerMap.end() && "should not fail populating callerMap"); + kernelBinning->serialize(os); } -bool -System::findCaller(std::string callee, std::string caller) const -{ - typedef multimap::const_iterator iter; - pair range; - - range = callerMap.equal_range(callee); - for (iter i = range.first; i != range.second; ++i) { - if ((*i).second == caller) - return true; - } - return false; -} void -System::dumpState(ExecContext *xc) const -{ - if (xc->swCtx) { - stack copy(xc->swCtx->callStack); - if (copy.empty()) - return; - DPRINTF(TCPIP, "xc->swCtx, size: %d:\n", copy.size()); - fnCall *top; - DPRINTF(TCPIP, "|| call : %d\n",xc->swCtx->calls); - for (top = copy.top(); !copy.empty(); copy.pop() ) { - top = copy.top(); - DPRINTF(TCPIP, "|| %13s : %s \n", top->name, top->myBin->name()); - } - } -} - -Stats::MainBin * -System::getBin(const std::string &name) -{ - std::map::const_iterator i; - i = fnBins.find(name); - if (i == fnBins.end()) - panic("trying to getBin %s that is not on system map!", name); - return (*i).second; -} - -SWContext * -System::findContext(Addr pcb) +System::unserialize(Checkpoint *cp, const string §ion) { - std::map::const_iterator iter; - iter = swCtxMap.find(pcb); - if (iter != swCtxMap.end()) { - SWContext *ctx = (*iter).second; - assert(ctx != NULL && "should never have a null ctx in ctxMap"); - return ctx; - } else - return NULL; + kernelBinning->unserialize(cp, section); } void -System::serialize(std::ostream &os) +System::printSystems() { - if (bin == true) { - map::const_iterator iter, end; - iter = swCtxMap.begin(); - end = swCtxMap.end(); - - int numCtxs = swCtxMap.size(); - SERIALIZE_SCALAR(numCtxs); - SWContext *ctx; - for (int i = 0; iter != end; ++i, ++iter) { - paramOut(os, csprintf("Addr[%d]",i), (*iter).first); - ctx = (*iter).second; - paramOut(os, csprintf("calls[%d]",i), ctx->calls); - - stack *stack = &(ctx->callStack); - fnCall *top; - int size = stack->size(); - paramOut(os, csprintf("stacksize[%d]",i), size); - for (int j=0; jtop(); - paramOut(os, csprintf("ctx[%d].stackpos[%d]",i,j), - top->name); - delete top; - stack->pop(); - } - } + vector::iterator i = systemList.begin(); + vector::iterator end = systemList.end(); + for (; i != end; ++i) { + System *sys = *i; + cerr << "System " << sys->name() << ": " << hex << sys << endl; } } +extern "C" void -System::unserialize(Checkpoint *cp, const std::string §ion) +printSystems() { - if (bin == true) { - int numCtxs; - UNSERIALIZE_SCALAR(numCtxs); - - SWContext *ctx; - Addr addr; - int size; - for(int i = 0; i < numCtxs; ++i) { - ctx = new SWContext; - paramIn(cp, section, csprintf("Addr[%d]",i), addr); - paramIn(cp, section, csprintf("calls[%d]",i), ctx->calls); - - paramIn(cp, section, csprintf("stacksize[%d]",i), size); - - vector calls; - fnCall *call; - for (int j = 0; j < size; ++j) { - call = new fnCall; - paramIn(cp, section, csprintf("ctx[%d].stackpos[%d]",i,j), - call->name); - call->myBin = getBin(call->name); - calls.push_back(call); - } - - for (int j=size-1; j>=0; --j) { - ctx->callStack.push(calls[j]); - } - - addContext(addr, ctx); - } - } + System::printSystems(); } DEFINE_SIM_OBJECT_CLASS_NAME("System", System) diff --git a/sim/system.hh b/sim/system.hh index da974cfdd..05b97ad62 100644 --- a/sim/system.hh +++ b/sim/system.hh @@ -37,80 +37,112 @@ #include "cpu/pc_event.hh" #include "kern/system_events.hh" #include "sim/sim_object.hh" -#include "sim/sw_context.hh" class MemoryController; class PhysicalMemory; class Platform; class RemoteGDB; class GDBListener; - +class ObjectFile; class ExecContext; +namespace Kernel { class Binning; } class System : public SimObject { - // lisa's binning stuff - private: - std::map fnBins; - std::map swCtxMap; + public: + MemoryController *memctrl; + PhysicalMemory *physmem; + Platform *platform; + PCEventQueue pcEventQueue; + uint64_t init_param; - protected: - std::vector fnEvents; + std::vector execContexts; - public: - Stats::Scalar<> fnCalls; - Stats::MainBin *Kernel; - Stats::MainBin *User; + /** kernel Symbol table */ + SymbolTable *kernelSymtab; - Stats::MainBin * getBin(const std::string &name); - bool findCaller(std::string, std::string) const; + /** console symbol table */ + SymbolTable *consoleSymtab; - SWContext *findContext(Addr pcb); - bool addContext(Addr pcb, SWContext *ctx) { - return (swCtxMap.insert(make_pair(pcb, ctx))).second; - } - void remContext(Addr pcb) { - swCtxMap.erase(pcb); - return; - } - void dumpState(ExecContext *xc) const; + /** Object pointer for the kernel code */ + ObjectFile *kernel; - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); + /** Object pointer for the console code */ + ObjectFile *console; + /** Object pointer for the PAL code */ + ObjectFile *pal; - private: - std::multimap callerMap; - void populateMap(std::string caller, std::string callee); -// + /** Begining of kernel code */ + Addr kernelStart; - public: - const uint64_t init_param; - MemoryController *memCtrl; - PhysicalMemory *physmem; - Platform *platform; - bool bin; - std::vector binned_fns; + /** End of kernel code */ + Addr kernelEnd; - PCEventQueue pcEventQueue; + /** Entry point in the kernel to start at */ + Addr kernelEntry; - std::vector execContexts; + Kernel::Binning *kernelBinning; - std::string readfile; +#ifdef DEBUG + /** Event to halt the simulator if the console calls panic() */ + BreakPCEvent *consolePanicEvent; +#endif - virtual int registerExecContext(ExecContext *xc); - virtual void replaceExecContext(int xcIndex, ExecContext *xc); + public: + std::vector remoteGDB; + std::vector gdbListen; + bool breakpoint(); public: - System(const std::string _name, const uint64_t _init_param, - MemoryController *, PhysicalMemory *, const bool, - const std::vector &binned_fns); + struct Params + { + std::string name; + MemoryController *memctrl; + PhysicalMemory *physmem; + uint64_t init_param; + bool bin; + std::vector binned_fns; + + std::string kernel_path; + std::string console_path; + std::string palcode; + std::string boot_osflags; + + std::string readfile; + uint64_t system_type; + uint64_t system_rev; + }; + Params *params; + + System(Params *p); ~System(); - virtual Addr getKernelStart() const = 0; - virtual Addr getKernelEnd() const = 0; - virtual Addr getKernelEntry() const = 0; - virtual bool breakpoint() = 0; + public: + /** + * Returns the addess the kernel starts at. + * @return address the kernel starts at + */ + Addr getKernelStart() const { return kernelStart; } + + /** + * Returns the addess the kernel ends at. + * @return address the kernel ends at + */ + Addr getKernelEnd() const { return kernelEnd; } + + /** + * Returns the addess the entry point to the kernel code. + * @return entry point of the kernel code + */ + Addr getKernelEntry() const { return kernelEntry; } + + int registerExecContext(ExecContext *xc); + void replaceExecContext(ExecContext *xc, int xcIndex); + + void regStats(); + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); public: //////////////////////////////////////////// -- 2.30.2