- 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
This commit is contained in:
parent
5786f4cb8e
commit
9023f5c96d
21 changed files with 731 additions and 1095 deletions
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
//
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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<fnCall *> *stack = &(swCtx->callStack);
|
||||
fnCall *top;
|
||||
int size = stack->size();
|
||||
SERIALIZE_SCALAR(size);
|
||||
|
||||
for (int j=0; j<size; ++j) {
|
||||
top = stack->top();
|
||||
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<fnCall *> calls;
|
||||
fnCall *call;
|
||||
for (int i=0; i<size; ++i) {
|
||||
call = new fnCall;
|
||||
paramIn(cp, section, csprintf("stackpos[%d]",i), call->name);
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -42,12 +42,12 @@ class BaseCPU;
|
|||
|
||||
#ifdef FULL_SYSTEM
|
||||
|
||||
#include "targetarch/alpha_memory.hh"
|
||||
class MemoryController;
|
||||
|
||||
#include "kern/kernel_stats.hh"
|
||||
#include "sim/system.hh"
|
||||
#include "sim/sw_context.hh"
|
||||
#include "targetarch/alpha_memory.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);
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -30,134 +30,82 @@
|
|||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
#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
|
||||
namespace Kernel {
|
||||
|
||||
const char *modestr[] = { "kernel", "user", "idle" };
|
||||
|
||||
Statistics::Statistics(ExecContext *context)
|
||||
: xc(context), idleProcess((Addr)-1), themode(kernel), lastModeTick(0),
|
||||
iplLast(0), iplLastTick(0)
|
||||
{
|
||||
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; }
|
||||
}
|
||||
|
||||
void
|
||||
KernelStats::regStats(const string &name)
|
||||
{ data->regStats(name); }
|
||||
|
||||
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<Tru64>::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++; }
|
||||
Statistics::setIdleProcess(Addr idlepcbb)
|
||||
{
|
||||
assert(themode == kernel);
|
||||
idleProcess = idlepcbb;
|
||||
themode = idle;
|
||||
changeMode(themode);
|
||||
}
|
||||
|
||||
void
|
||||
KernelStats::quiesce()
|
||||
{ data->_quiesce++; }
|
||||
Statistics::changeMode(cpu_mode newmode)
|
||||
{
|
||||
_mode[newmode]++;
|
||||
|
||||
if (newmode == themode)
|
||||
return;
|
||||
|
||||
DPRINTF(Context, "old mode=%-8s new mode=%-8s\n",
|
||||
modestr[themode], modestr[newmode]);
|
||||
|
||||
_modeGood[newmode]++;
|
||||
_modeTicks[themode] += curTick - lastModeTick;
|
||||
|
||||
xc->system->kernelBinning->changeMode(newmode);
|
||||
|
||||
lastModeTick = curTick;
|
||||
themode = newmode;
|
||||
}
|
||||
|
||||
void
|
||||
KernelStats::ivlb()
|
||||
{ data->_ivlb++; }
|
||||
|
||||
void
|
||||
KernelStats::ivle()
|
||||
{ data->_ivle++; }
|
||||
|
||||
void
|
||||
KernelStats::hwrei()
|
||||
{ data->_hwrei++; }
|
||||
|
||||
void
|
||||
KernelStats::fault(Fault fault)
|
||||
{ data->_faults[fault]++; }
|
||||
|
||||
void
|
||||
KernelStats::swpipl(int ipl)
|
||||
{ data->swpipl(ipl); }
|
||||
|
||||
void
|
||||
KernelStats::mode(bool user)
|
||||
{ data->mode(user); }
|
||||
|
||||
void
|
||||
KernelStats::context(Addr old_pcbb, Addr new_pcbb)
|
||||
{ data->_swap_context++; }
|
||||
|
||||
void
|
||||
KernelStats::callpal(int code)
|
||||
{ data->callpal(code); }
|
||||
|
||||
|
||||
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
|
||||
KSData::callpal(int code)
|
||||
Statistics::context(Addr oldpcbb, Addr newpcbb)
|
||||
{
|
||||
assert(themode != user);
|
||||
|
||||
_swap_context++;
|
||||
changeMode(newpcbb == idleProcess ? idle : kernel);
|
||||
}
|
||||
|
||||
void
|
||||
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<Tru64>::validSyscallNumber(number)) {
|
||||
int cvtnum = SystemCalls<Tru64>::convert(number);
|
||||
_syscall[cvtnum]++;
|
||||
}
|
||||
}
|
||||
case PAL::callsys: {
|
||||
int number = xc->regs.intRegFile[0];
|
||||
if (SystemCalls<Tru64>::validSyscallNumber(number)) {
|
||||
int cvtnum = SystemCalls<Tru64>::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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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::serialize(ostream &os)
|
||||
{
|
||||
int exemode = themode;
|
||||
SERIALIZE_SCALAR(exemode);
|
||||
}
|
||||
|
||||
void
|
||||
Statistics::unserialize(Checkpoint *cp, const string §ion)
|
||||
{
|
||||
int exemode;
|
||||
UNSERIALIZE_SCALAR(exemode);
|
||||
themode = (cpu_mode)exemode;
|
||||
}
|
||||
|
||||
/* end namespace Kernel */ }
|
||||
|
|
|
@ -29,35 +29,165 @@
|
|||
#ifndef __KERNEL_STATS_HH__
|
||||
#define __KERNEL_STATS_HH__
|
||||
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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<fnCall *> callStack;
|
||||
};
|
||||
|
||||
std::map<const std::string, Stats::MainBin *> fnBins;
|
||||
std::map<const Addr, SWContext *> swCtxMap;
|
||||
|
||||
std::multimap<const std::string, std::string> callerMap;
|
||||
void populateMap(std::string caller, std::string callee);
|
||||
|
||||
std::vector<FnEvent *> 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<std::string> binned_fns;
|
||||
|
||||
private:
|
||||
Stats::MainBin *modeBin[3];
|
||||
|
||||
public:
|
||||
KernelStats(ExecContext *_xc, BaseCPU *_cpu);
|
||||
~KernelStats();
|
||||
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:
|
||||
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();
|
||||
|
||||
void fault(Fault fault);
|
||||
void swpipl(int ipl);
|
||||
void mode(bool user);
|
||||
void context(Addr old_pcbb, Addr new_pcbb);
|
||||
void callpal(int code);
|
||||
public:
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
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 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__
|
||||
|
|
|
@ -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<string> &_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);
|
||||
|
||||
if (kernelSymtab->findAddress("alpha_switch_to", addr) &&
|
||||
DTRACE(Thread))
|
||||
printThreadEvent->schedule(addr+sizeof(MachInst)*6);
|
||||
idleStartEvent = new IdleStartEvent(&pcEventQueue, "cpu_idle", this);
|
||||
if (kernelSymtab->findAddress("cpu_idle", addr))
|
||||
idleStartEvent->schedule(addr);
|
||||
|
||||
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<bool> bin;
|
||||
SimObjectParam<MemoryController *> mem_ctl;
|
||||
SimObjectParam<PhysicalMemory *> physmem;
|
||||
Param<uint64_t> init_param;
|
||||
|
||||
Param<string> kernel_code;
|
||||
Param<string> console_code;
|
||||
Param<string> pal_code;
|
||||
Param<string> boot_osflags;
|
||||
VectorParam<string> binned_fns;
|
||||
|
||||
Param<string> boot_osflags;
|
||||
Param<string> readfile;
|
||||
Param<unsigned int> init_param;
|
||||
|
||||
Param<uint64_t> system_type;
|
||||
Param<uint64_t> system_rev;
|
||||
|
||||
Param<bool> bin;
|
||||
VectorParam<string> 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);
|
||||
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;
|
||||
|
||||
sys->readfile = readfile;
|
||||
return sys;
|
||||
return new LinuxSystem(p);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem)
|
||||
|
||||
|
|
|
@ -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 <vector>
|
||||
|
||||
#include "sim/system.hh"
|
||||
#include "sim/host.hh"
|
||||
#include "sim/system.hh"
|
||||
#include "targetarch/isa_traits.hh"
|
||||
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* 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<string> binned_fns;
|
||||
/** Grab the PCBB of the idle process when it starts */
|
||||
IdleStartEvent *idleStartEvent;
|
||||
|
||||
public:
|
||||
std::vector<RemoteGDB *> remoteGDB;
|
||||
std::vector<GDBListener *> 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<std::string> &_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__
|
||||
|
|
|
@ -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--;
|
||||
|
||||
//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);
|
||||
xc->system->kernelBinning->call(xc, mybin);
|
||||
}
|
||||
|
||||
void
|
||||
IdleStartEvent::process(ExecContext *xc)
|
||||
{
|
||||
xc->kernelStats->setIdleProcess(xc->regs.ipr[AlphaISA::IPR_PALtemp23]);
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<string> &_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<bool> bin;
|
||||
SimObjectParam<MemoryController *> mem_ctl;
|
||||
SimObjectParam<PhysicalMemory *> physmem;
|
||||
Param<unsigned int> init_param;
|
||||
|
||||
Param<string> kernel_code;
|
||||
Param<string> console_code;
|
||||
Param<string> pal_code;
|
||||
|
||||
Param<string> boot_osflags;
|
||||
VectorParam<string> binned_fns;
|
||||
Param<string> readfile;
|
||||
Param<unsigned int> init_param;
|
||||
|
||||
Param<uint64_t> system_type;
|
||||
Param<uint64_t> system_rev;
|
||||
|
||||
Param<bool> bin;
|
||||
VectorParam<string> 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);
|
||||
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 sys;
|
||||
return new Tru64System(p);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("Tru64System", Tru64System)
|
||||
|
|
|
@ -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 <map>
|
||||
#include <vector>
|
||||
#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<string> binned_fns;
|
||||
|
||||
public:
|
||||
std::vector<RemoteGDB *> remoteGDB;
|
||||
std::vector<GDBListener *> 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<string> &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__
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
330
sim/system.cc
330
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 *> 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<string> &binned_fns)
|
||||
extern SymbolTable *debugSymbolTable;
|
||||
|
||||
: SimObject(_name),
|
||||
init_param(_init_param),
|
||||
memCtrl(_memCtrl),
|
||||
physmem(_physmem),
|
||||
bin(_bin),
|
||||
binned_fns(binned_fns)
|
||||
System::System(Params *p)
|
||||
: SimObject(p->name), memctrl(p->memctrl), physmem(p->physmem),
|
||||
init_param(p->init_param), params(p)
|
||||
{
|
||||
// increment the number of running systems
|
||||
numSystemsRunning++;
|
||||
|
||||
// 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));
|
||||
kernelSymtab = new SymbolTable;
|
||||
consoleSymtab = new SymbolTable;
|
||||
debugSymbolTable = kernelSymtab;
|
||||
|
||||
Stats::MainBin *Bin;
|
||||
/**
|
||||
* 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);
|
||||
|
||||
fnEvents.resize(end>>1);
|
||||
// Load Console Code
|
||||
console = createObjectFile(params->console_path);
|
||||
if (console == NULL)
|
||||
fatal("Could not load console file %s", params->console_path);
|
||||
|
||||
for (int i = 0; i < end; i +=2) {
|
||||
Bin = new Stats::MainBin(binned_fns[i]);
|
||||
fnBins.insert(make_pair(binned_fns[i], Bin));
|
||||
// Load pal file
|
||||
pal = createObjectFile(params->palcode);
|
||||
if (pal == NULL)
|
||||
fatal("Could not load PALcode file %s", params->palcode);
|
||||
|
||||
fnEvents[(i>>1)] = new FnEvent(&pcEventQueue, binned_fns[i], this);
|
||||
|
||||
if (binned_fns[i+1] == "null")
|
||||
populateMap(binned_fns[i], "");
|
||||
else
|
||||
populateMap(binned_fns[i], binned_fns[i+1]);
|
||||
}
|
||||
// Load program sections into memory
|
||||
pal->loadSections(physmem, true);
|
||||
console->loadSections(physmem, true);
|
||||
kernel->loadSections(physmem, true);
|
||||
|
||||
fnCalls
|
||||
.name(name() + ":fnCalls")
|
||||
.desc("all fn calls being tracked")
|
||||
;
|
||||
// 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
|
||||
if (!hwrpb)
|
||||
panic("could not translate hwrpb addr\n");
|
||||
|
||||
*(uint64_t*)(hwrpb+0x50) = params->system_type;
|
||||
*(uint64_t*)(hwrpb+0x58) = params->system_rev;
|
||||
} else
|
||||
Kernel = NULL;
|
||||
}
|
||||
panic("could not find hwrpb\n");
|
||||
|
||||
// increment the number of running systms
|
||||
numSystemsRunning++;
|
||||
|
||||
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,8 +205,27 @@ System::replaceExecContext(int xcIndex, ExecContext *xc)
|
|||
}
|
||||
|
||||
execContexts[xcIndex] = xc;
|
||||
remoteGDB[xcIndex]->replaceExecContext(xc);
|
||||
}
|
||||
|
||||
void
|
||||
System::regStats()
|
||||
{
|
||||
kernelBinning->regStats(name() + ".kern");
|
||||
}
|
||||
|
||||
void
|
||||
System::serialize(ostream &os)
|
||||
{
|
||||
kernelBinning->serialize(os);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
System::unserialize(Checkpoint *cp, const string §ion)
|
||||
{
|
||||
kernelBinning->unserialize(cp, section);
|
||||
}
|
||||
|
||||
void
|
||||
System::printSystems()
|
||||
|
@ -142,134 +245,5 @@ printSystems()
|
|||
System::printSystems();
|
||||
}
|
||||
|
||||
void
|
||||
System::populateMap(std::string callee, std::string caller)
|
||||
{
|
||||
multimap<const string, string>::const_iterator i;
|
||||
i = callerMap.insert(make_pair(callee, caller));
|
||||
assert(i != callerMap.end() && "should not fail populating callerMap");
|
||||
}
|
||||
|
||||
bool
|
||||
System::findCaller(std::string callee, std::string caller) const
|
||||
{
|
||||
typedef multimap<const std::string, std::string>::const_iterator iter;
|
||||
pair<iter, iter> 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<fnCall *> 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 std::string, Stats::MainBin *>::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)
|
||||
{
|
||||
std::map<Addr, SWContext *>::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;
|
||||
}
|
||||
|
||||
void
|
||||
System::serialize(std::ostream &os)
|
||||
{
|
||||
if (bin == true) {
|
||||
map<const Addr, SWContext *>::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<fnCall *> *stack = &(ctx->callStack);
|
||||
fnCall *top;
|
||||
int size = stack->size();
|
||||
paramOut(os, csprintf("stacksize[%d]",i), size);
|
||||
for (int j=0; j<size; ++j) {
|
||||
top = stack->top();
|
||||
paramOut(os, csprintf("ctx[%d].stackpos[%d]",i,j),
|
||||
top->name);
|
||||
delete top;
|
||||
stack->pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
System::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
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<fnCall *> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
|
||||
|
||||
|
|
136
sim/system.hh
136
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<const std::string, Stats::MainBin *> fnBins;
|
||||
std::map<const Addr, SWContext *> swCtxMap;
|
||||
|
||||
protected:
|
||||
std::vector<FnEvent *> fnEvents;
|
||||
|
||||
public:
|
||||
Stats::Scalar<> fnCalls;
|
||||
Stats::MainBin *Kernel;
|
||||
Stats::MainBin *User;
|
||||
|
||||
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(make_pair(pcb, ctx))).second;
|
||||
}
|
||||
void remContext(Addr pcb) {
|
||||
swCtxMap.erase(pcb);
|
||||
return;
|
||||
}
|
||||
void dumpState(ExecContext *xc) const;
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
|
||||
private:
|
||||
std::multimap<const std::string, std::string> callerMap;
|
||||
void populateMap(std::string caller, std::string callee);
|
||||
//
|
||||
|
||||
public:
|
||||
const uint64_t init_param;
|
||||
MemoryController *memCtrl;
|
||||
MemoryController *memctrl;
|
||||
PhysicalMemory *physmem;
|
||||
Platform *platform;
|
||||
bool bin;
|
||||
std::vector<string> binned_fns;
|
||||
|
||||
PCEventQueue pcEventQueue;
|
||||
uint64_t init_param;
|
||||
|
||||
std::vector<ExecContext *> execContexts;
|
||||
|
||||
std::string readfile;
|
||||
/** kernel Symbol table */
|
||||
SymbolTable *kernelSymtab;
|
||||
|
||||
virtual int registerExecContext(ExecContext *xc);
|
||||
virtual void replaceExecContext(int xcIndex, ExecContext *xc);
|
||||
/** console symbol table */
|
||||
SymbolTable *consoleSymtab;
|
||||
|
||||
/** Object pointer for the kernel code */
|
||||
ObjectFile *kernel;
|
||||
|
||||
/** Object pointer for the console code */
|
||||
ObjectFile *console;
|
||||
|
||||
/** Object pointer for the PAL code */
|
||||
ObjectFile *pal;
|
||||
|
||||
/** Begining of kernel code */
|
||||
Addr kernelStart;
|
||||
|
||||
/** End of kernel code */
|
||||
Addr kernelEnd;
|
||||
|
||||
/** Entry point in the kernel to start at */
|
||||
Addr kernelEntry;
|
||||
|
||||
Kernel::Binning *kernelBinning;
|
||||
|
||||
#ifdef DEBUG
|
||||
/** Event to halt the simulator if the console calls panic() */
|
||||
BreakPCEvent *consolePanicEvent;
|
||||
#endif
|
||||
|
||||
public:
|
||||
System(const std::string _name, const uint64_t _init_param,
|
||||
MemoryController *, PhysicalMemory *, const bool,
|
||||
const std::vector<string> &binned_fns);
|
||||
std::vector<RemoteGDB *> remoteGDB;
|
||||
std::vector<GDBListener *> gdbListen;
|
||||
bool breakpoint();
|
||||
|
||||
public:
|
||||
struct Params
|
||||
{
|
||||
std::string name;
|
||||
MemoryController *memctrl;
|
||||
PhysicalMemory *physmem;
|
||||
uint64_t init_param;
|
||||
bool bin;
|
||||
std::vector<std::string> 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:
|
||||
////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in a new issue