sim: Add helper functions that add PCEvents with custom arguments

This changeset adds support for forwarding arguments to the PC
event constructors to following methods:

addKernelFuncEvent
addFuncEvent

Additionally, this changeset adds the following helper method to the
System base class:

addFuncEventOrPanic - Hook a PCEvent to a symbol, panic on failure.

addKernelFuncEventOrPanic - Hook a PCEvent to a kernel symbol, panic
                            on failure.


System implementations have been updated to use the new functionality
where appropriate.
This commit is contained in:
Andreas Sandberg 2013-04-22 13:20:31 -04:00
parent c9e4678c16
commit aa08069b3f
4 changed files with 70 additions and 34 deletions

View file

@ -120,14 +120,10 @@ LinuxAlphaSystem::setupFuncEvents()
{
AlphaSystem::setupFuncEvents();
#ifndef NDEBUG
kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
if (!kernelPanicEvent)
panic("could not find kernel symbol \'panic\'");
kernelPanicEvent = addKernelFuncEventOrPanic<BreakPCEvent>("panic");
#if 0
kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
if (!kernelDieEvent)
panic("could not find kernel symbol \'die_if_kernel\'");
kernelDieEvent = addKernelFuncEventOrPanic<BreakPCEvent>("die_if_kernel");
#endif
#endif

View file

@ -51,14 +51,10 @@ Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p)
}
#ifdef DEBUG
kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
if (!kernelPanicEvent)
panic("could not find kernel symbol \'panic\'");
kernelPanicEvent = addKernelFuncEventOrPanic<BreakPCEvent>("panic");
#endif
badaddrEvent = addKernelFuncEvent<BadAddrEvent>("badaddr");
if (!badaddrEvent)
panic("could not find kernel symbol \'badaddr\'");
badaddrEvent = addKernelFuncEventOrPanic<BadAddrEvent>("badaddr");
skipPowerStateEvent =
addKernelFuncEvent<SkipFuncEvent>("tl_v48_capture_power_state");

View file

@ -65,28 +65,17 @@ LinuxArmSystem::LinuxArmSystem(Params *p)
enableContextSwitchStatsDump(p->enable_context_switch_stats_dump)
{
#ifndef NDEBUG
kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
if (!kernelPanicEvent)
panic("could not find kernel symbol \'panic\'");
kernelPanicEvent = addKernelFuncEventOrPanic<BreakPCEvent>("panic");
#endif
// With ARM udelay() is #defined to __udelay
Addr addr = 0;
if (kernelSymtab->findAddress("__udelay", addr)) {
uDelaySkipEvent = new UDelayEvent(&pcEventQueue, "__udelay",
fixFuncEventAddr(addr), 1000, 0);
} else {
panic("couldn't find kernel symbol \'udelay\'");
}
uDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
"__udelay", "__udelay", 1000, 0);
// constant arguments to udelay() have some precomputation done ahead of
// time. Constant comes from code.
if (kernelSymtab->findAddress("__const_udelay", addr)) {
constUDelaySkipEvent = new UDelayEvent(&pcEventQueue, "__const_udelay",
fixFuncEventAddr(addr), 1000, 107374);
} else {
panic("couldn't find kernel symbol \'udelay\'");
}
constUDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
"__const_udelay", "__const_udelay", 1000, 107374);
secDataPtrAddr = 0;
secDataAddr = 0;

View file

@ -48,6 +48,7 @@
#define __SYSTEM_HH__
#include <string>
#include <utility>
#include <vector>
#include "base/loader/symtab.hh"
@ -353,30 +354,84 @@ class System : public MemObject
panic("Base fixFuncEventAddr not implemented.\n");
}
/** @{ */
/**
* Add a function-based event to the given function, to be looked
* up in the specified symbol table.
*
* The ...OrPanic flavor of the method causes the simulator to
* panic if the symbol can't be found.
*
* @param symtab Symbol table to use for look up.
* @param lbl Function to hook the event to.
* @param desc Description to be passed to the event.
* @param args Arguments to be forwarded to the event constructor.
*/
template <class T>
T *addFuncEvent(SymbolTable *symtab, const char *lbl)
template <class T, typename... Args>
T *addFuncEvent(const SymbolTable *symtab, const char *lbl,
const std::string &desc, Args... args)
{
Addr addr = 0; // initialize only to avoid compiler warning
if (symtab->findAddress(lbl, addr)) {
T *ev = new T(&pcEventQueue, lbl, fixFuncEventAddr(addr));
T *ev = new T(&pcEventQueue, desc, fixFuncEventAddr(addr),
std::forward<Args>(args)...);
return ev;
}
return NULL;
}
/** Add a function-based event to kernel code. */
template <class T>
T *addKernelFuncEvent(const char *lbl)
T *addFuncEvent(const SymbolTable *symtab, const char *lbl)
{
return addFuncEvent<T>(kernelSymtab, lbl);
return addFuncEvent<T>(symtab, lbl, lbl);
}
template <class T, typename... Args>
T *addFuncEventOrPanic(const SymbolTable *symtab, const char *lbl,
Args... args)
{
T *e(addFuncEvent<T>(symtab, lbl, std::forward<Args>(args)...));
if (!e)
panic("Failed to find symbol '%s'", lbl);
return e;
}
/** @} */
/** @{ */
/**
* Add a function-based event to a kernel symbol.
*
* These functions work like their addFuncEvent() and
* addFuncEventOrPanic() counterparts. The only difference is that
* they automatically use the kernel symbol table. All arguments
* are forwarded to the underlying method.
*
* @see addFuncEvent()
* @see addFuncEventOrPanic()
*
* @param lbl Function to hook the event to.
* @param args Arguments to be passed to addFuncEvent
*/
template <class T, typename... Args>
T *addKernelFuncEvent(const char *lbl, Args... args)
{
return addFuncEvent<T>(kernelSymtab, lbl,
std::forward<Args>(args)...);
}
template <class T, typename... Args>
T *addKernelFuncEventOrPanic(const char *lbl, Args... args)
{
T *e(addFuncEvent<T>(kernelSymtab, lbl,
std::forward<Args>(args)...));
if (!e)
panic("Failed to find kernel symbol '%s'", lbl);
return e;
}
/** @} */
public:
std::vector<BaseRemoteGDB *> remoteGDB;
std::vector<GDBListener *> gdbListen;