diff options
Diffstat (limited to 'kern')
-rw-r--r-- | kern/kernel_stats.cc | 28 | ||||
-rw-r--r-- | kern/kernel_stats.hh | 7 | ||||
-rw-r--r-- | kern/linux/linux_system.cc | 18 | ||||
-rw-r--r-- | kern/linux/linux_system.hh | 14 | ||||
-rw-r--r-- | kern/system_events.cc | 14 | ||||
-rw-r--r-- | kern/system_events.hh | 20 |
6 files changed, 84 insertions, 17 deletions
diff --git a/kern/kernel_stats.cc b/kern/kernel_stats.cc index c8c04e6d1..c08ee08f7 100644 --- a/kern/kernel_stats.cc +++ b/kern/kernel_stats.cc @@ -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); } diff --git a/kern/kernel_stats.hh b/kern/kernel_stats.hh index 8339c578c..af93eb95c 100644 --- a/kern/kernel_stats.hh +++ b/kern/kernel_stats.hh @@ -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); diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc index 10641de87..91ad45157 100644 --- a/kern/linux/linux_system.cc +++ b/kern/linux/linux_system.cc @@ -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); } diff --git a/kern/linux/linux_system.hh b/kern/linux/linux_system.hh index 707204607..f5fd2b06b 100644 --- a/kern/linux/linux_system.hh +++ b/kern/linux/linux_system.hh @@ -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; diff --git a/kern/system_events.cc b/kern/system_events.cc index 91daf53ca..b6526d193 100644 --- a/kern/system_events.cc +++ b/kern/system_events.cc @@ -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); +} diff --git a/kern/system_events.hh b/kern/system_events.hh index 95027572f..8a8549d03 100644 --- a/kern/system_events.hh +++ b/kern/system_events.hh @@ -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__ |