added system option to bin interrupt code seperately.
arch/alpha/ev5.cc: set the mode explictly rather than having a bool user/notuser cpu/simple_cpu/simple_cpu.hh: there is no class Kernel kern/kernel_stats.cc: use cpu_mode_num kern/kernel_stats.hh: add interrupt mode and use cpu_mode_num rather than constant kern/linux/linux_system.cc: kern/linux/linux_system.hh: kern/system_events.cc: kern/system_events.hh: add events to change the mode to/from interrupt sim/system.cc: sim/system.hh: add a pal symbol table --HG-- extra : convert_revision : 9d30e826b72122062a5ea12d094f94760e75c66a
This commit is contained in:
parent
8efb592e0b
commit
af620e1187
10 changed files with 97 additions and 20 deletions
|
@ -447,7 +447,10 @@ ExecContext::setIpr(int idx, uint64_t val)
|
|||
break;
|
||||
|
||||
case AlphaISA::IPR_DTB_CM:
|
||||
kernelStats->mode((val & 0x18) != 0);
|
||||
if (val & 0x18)
|
||||
kernelStats->mode(Kernel::user);
|
||||
else
|
||||
kernelStats->mode(Kernel::kernel);
|
||||
|
||||
case AlphaISA::IPR_ICM:
|
||||
// only write two mode bits - processor mode
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
// forward declarations
|
||||
#ifdef FULL_SYSTEM
|
||||
class Processor;
|
||||
class Kernel;
|
||||
class AlphaITB;
|
||||
class AlphaDTB;
|
||||
class PhysicalMemory;
|
||||
|
|
|
@ -45,12 +45,13 @@ using namespace Stats;
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
const char *modestr[] = { "kernel", "user", "idle" };
|
||||
const char *modestr[] = { "kernel", "user", "idle", "interrupt" };
|
||||
|
||||
Statistics::Statistics(ExecContext *context)
|
||||
: xc(context), idleProcess((Addr)-1), themode(kernel), lastModeTick(0),
|
||||
iplLast(0), iplLastTick(0)
|
||||
{
|
||||
bin_int = xc->system->params->bin_int;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -153,20 +154,20 @@ Statistics::regStats(const string &_name)
|
|||
}
|
||||
|
||||
_mode
|
||||
.init(3)
|
||||
.init(cpu_mode_num)
|
||||
.name(name() + ".mode_switch")
|
||||
.desc("number of protection mode switches")
|
||||
;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int i = 0; i < cpu_mode_num; ++i)
|
||||
_mode.subname(i, modestr[i]);
|
||||
|
||||
_modeGood
|
||||
.init(3)
|
||||
.init(cpu_mode_num)
|
||||
.name(name() + ".mode_good")
|
||||
;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int i = 0; i < cpu_mode_num; ++i)
|
||||
_modeGood.subname(i, modestr[i]);
|
||||
|
||||
_modeFraction
|
||||
|
@ -175,18 +176,18 @@ Statistics::regStats(const string &_name)
|
|||
.flags(total)
|
||||
;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int i = 0; i < cpu_mode_num; ++i)
|
||||
_modeFraction.subname(i, modestr[i]);
|
||||
|
||||
_modeFraction = _modeGood / _mode;
|
||||
|
||||
_modeTicks
|
||||
.init(3)
|
||||
.init(cpu_mode_num)
|
||||
.name(name() + ".mode_ticks")
|
||||
.desc("number of ticks spent at the given mode")
|
||||
.flags(pdf)
|
||||
;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int i = 0; i < cpu_mode_num; ++i)
|
||||
_modeTicks.subname(i, modestr[i]);
|
||||
|
||||
_swap_context
|
||||
|
@ -198,7 +199,7 @@ Statistics::regStats(const string &_name)
|
|||
void
|
||||
Statistics::setIdleProcess(Addr idlepcbb)
|
||||
{
|
||||
assert(themode == kernel);
|
||||
assert(themode == kernel || themode == interrupt);
|
||||
idleProcess = idlepcbb;
|
||||
themode = idle;
|
||||
changeMode(themode);
|
||||
|
@ -241,14 +242,17 @@ Statistics::swpipl(int ipl)
|
|||
}
|
||||
|
||||
void
|
||||
Statistics::mode(bool usermode)
|
||||
Statistics::mode(cpu_mode newmode)
|
||||
{
|
||||
Addr pcbb = xc->regs.ipr[AlphaISA::IPR_PALtemp23];
|
||||
|
||||
cpu_mode newmode = usermode ? user : kernel;
|
||||
if (newmode == kernel && pcbb == idleProcess)
|
||||
if ((newmode == kernel || newmode == interrupt) &&
|
||||
pcbb == idleProcess)
|
||||
newmode = idle;
|
||||
|
||||
if (bin_int == false && newmode == interrupt)
|
||||
newmode = kernel;
|
||||
|
||||
changeMode(newmode);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ enum Fault;
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
enum cpu_mode { kernel, user, idle, cpu_mode_num };
|
||||
enum cpu_mode { kernel, user, idle, interrupt, cpu_mode_num };
|
||||
extern const char *modestr[];
|
||||
|
||||
class Binning
|
||||
|
@ -98,7 +98,7 @@ class Binning
|
|||
std::vector<std::string> binned_fns;
|
||||
|
||||
private:
|
||||
Stats::MainBin *modeBin[3];
|
||||
Stats::MainBin *modeBin[cpu_mode_num];
|
||||
|
||||
public:
|
||||
const bool bin;
|
||||
|
@ -133,6 +133,7 @@ class Statistics : public Serializable
|
|||
Addr idleProcess;
|
||||
cpu_mode themode;
|
||||
Tick lastModeTick;
|
||||
bool bin_int;
|
||||
|
||||
void changeMode(cpu_mode newmode);
|
||||
|
||||
|
@ -177,7 +178,7 @@ class Statistics : public Serializable
|
|||
void hwrei() { _hwrei++; }
|
||||
void fault(Fault fault) { _faults[fault]++; }
|
||||
void swpipl(int ipl);
|
||||
void mode(bool usermode);
|
||||
void mode(cpu_mode newmode);
|
||||
void context(Addr oldpcbb, Addr newpcbb);
|
||||
void callpal(int code);
|
||||
|
||||
|
|
|
@ -143,6 +143,16 @@ LinuxSystem::LinuxSystem(Params *p)
|
|||
printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo");
|
||||
if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread))
|
||||
printThreadEvent->schedule(addr + sizeof(MachInst) * 6);
|
||||
|
||||
intStartEvent = new InterruptStartEvent(&pcEventQueue, "intStartEvent");
|
||||
if (kernelSymtab->findAddress("do_entInt", addr))
|
||||
intStartEvent->schedule(addr + sizeof(MachInst) * 2);
|
||||
|
||||
intEndEvent = new InterruptEndEvent(&pcEventQueue, "intStartEvent");
|
||||
if (palSymtab->findAddress("Call_Pal_Rti", addr))
|
||||
intEndEvent->schedule(addr + sizeof(MachInst));
|
||||
else
|
||||
panic("could not find symbol\n");
|
||||
}
|
||||
|
||||
LinuxSystem::~LinuxSystem()
|
||||
|
@ -155,6 +165,8 @@ LinuxSystem::~LinuxSystem()
|
|||
delete skipCacheProbeEvent;
|
||||
delete debugPrintkEvent;
|
||||
delete idleStartEvent;
|
||||
delete printThreadEvent;
|
||||
delete intStartEvent;
|
||||
}
|
||||
|
||||
|
||||
|
@ -193,6 +205,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
|
|||
|
||||
Param<bool> bin;
|
||||
VectorParam<string> binned_fns;
|
||||
Param<bool> bin_int;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
|
||||
|
||||
|
@ -210,7 +223,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
|
|||
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")
|
||||
INIT_PARAM(binned_fns, "functions to be broken down and binned"),
|
||||
INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", false)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
|
||||
|
||||
|
@ -230,7 +244,7 @@ CREATE_SIM_OBJECT(LinuxSystem)
|
|||
p->system_rev = system_rev;
|
||||
p->bin = bin;
|
||||
p->binned_fns = binned_fns;
|
||||
|
||||
p->bin_int = bin_int;
|
||||
return new LinuxSystem(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -83,8 +83,22 @@ class LinuxSystem : public System
|
|||
*/
|
||||
LinuxSkipDelayLoopEvent *skipDelayLoopEvent;
|
||||
|
||||
/**
|
||||
* Event to print information about thread switches if the trace flag
|
||||
* Thread is set
|
||||
*/
|
||||
PrintThreadInfo *printThreadEvent;
|
||||
|
||||
/**
|
||||
* Event to bin Interrupts seperately from kernel code
|
||||
*/
|
||||
InterruptStartEvent *intStartEvent;
|
||||
|
||||
/**
|
||||
* Event to bin Interrupts seperately from kernel code
|
||||
*/
|
||||
InterruptEndEvent *intEndEvent;
|
||||
|
||||
/** Grab the PCBB of the idle process when it starts */
|
||||
IdleStartEvent *idleStartEvent;
|
||||
|
||||
|
|
|
@ -71,3 +71,17 @@ IdleStartEvent::process(ExecContext *xc)
|
|||
{
|
||||
xc->kernelStats->setIdleProcess(xc->regs.ipr[AlphaISA::IPR_PALtemp23]);
|
||||
}
|
||||
|
||||
void
|
||||
InterruptStartEvent::process(ExecContext *xc)
|
||||
{
|
||||
xc->kernelStats->mode(Kernel::interrupt);
|
||||
}
|
||||
|
||||
void
|
||||
InterruptEndEvent::process(ExecContext *xc)
|
||||
{
|
||||
// We go back to kernel, if we are user, inside the rti
|
||||
// pal code we will get switched to user because of the ICM write
|
||||
xc->kernelStats->mode(Kernel::kernel);
|
||||
}
|
||||
|
|
|
@ -64,4 +64,24 @@ class IdleStartEvent : public PCEvent
|
|||
{}
|
||||
virtual void process(ExecContext *xc);
|
||||
};
|
||||
|
||||
class InterruptStartEvent : public PCEvent
|
||||
{
|
||||
public:
|
||||
InterruptStartEvent(PCEventQueue *q, const std::string &desc)
|
||||
: PCEvent(q, desc)
|
||||
{}
|
||||
virtual void process(ExecContext *xc);
|
||||
};
|
||||
|
||||
class InterruptEndEvent : public PCEvent
|
||||
{
|
||||
public:
|
||||
InterruptEndEvent(PCEventQueue *q, const std::string &desc)
|
||||
: PCEvent(q, desc)
|
||||
{}
|
||||
virtual void process(ExecContext *xc);
|
||||
};
|
||||
|
||||
|
||||
#endif // __SYSTEM_EVENTS_HH__
|
||||
|
|
|
@ -55,6 +55,7 @@ System::System(Params *p)
|
|||
|
||||
kernelSymtab = new SymbolTable;
|
||||
consoleSymtab = new SymbolTable;
|
||||
palSymtab = new SymbolTable;
|
||||
debugSymbolTable = new SymbolTable;
|
||||
|
||||
/**
|
||||
|
@ -96,6 +97,9 @@ System::System(Params *p)
|
|||
if (!console->loadGlobalSymbols(consoleSymtab))
|
||||
panic("could not load console symbols\n");
|
||||
|
||||
if (!pal->loadGlobalSymbols(palSymtab))
|
||||
panic("could not load pal symbols\n");
|
||||
|
||||
if (!kernel->loadGlobalSymbols(debugSymbolTable))
|
||||
panic("could not load kernel symbols\n");
|
||||
|
||||
|
|
|
@ -64,6 +64,9 @@ class System : public SimObject
|
|||
/** console symbol table */
|
||||
SymbolTable *consoleSymtab;
|
||||
|
||||
/** pal symbol table */
|
||||
SymbolTable *palSymtab;
|
||||
|
||||
/** Object pointer for the kernel code */
|
||||
ObjectFile *kernel;
|
||||
|
||||
|
@ -103,6 +106,7 @@ class System : public SimObject
|
|||
uint64_t init_param;
|
||||
bool bin;
|
||||
std::vector<std::string> binned_fns;
|
||||
bool bin_int;
|
||||
|
||||
std::string kernel_path;
|
||||
std::string console_path;
|
||||
|
|
Loading…
Reference in a new issue