- 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:
Nathan Binkert 2004-08-20 11:35:31 -04:00
parent 5786f4cb8e
commit 9023f5c96d
21 changed files with 731 additions and 1095 deletions

View file

@ -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

View file

@ -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(&regs, 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:

View file

@ -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;

View file

@ -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();
//

View file

@ -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
}

View file

@ -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(&regs, 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 &section)
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
}

View file

@ -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);

View file

@ -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()) {

View file

@ -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 &section)
{
int exemode;
UNSERIALIZE_SCALAR(exemode);
themode = (cpu_mode)exemode;
}
/* end namespace Kernel */ }

View file

@ -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 &section);
};
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 &section);
};
/* end namespace Kernel */ }
#endif // __KERNEL_STATS_HH__

View file

@ -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)

View file

@ -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__

View file

@ -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]);
}

View file

@ -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__

View file

@ -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;

View file

@ -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)

View file

@ -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__

View file

@ -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",

View file

@ -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);

View file

@ -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 &section)
{
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 &section)
{
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)

View file

@ -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 &section);
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 &section);
public:
////////////////////////////////////////////