Add functions to System object to set up function-based events,
including automatically fixing up addresses to deal with optionally executed Alpha gp update prolog. SConscript: Remove freebsd_events.cc and linux_events.cc. base/remote_gdb.cc: cpu/pc_event.cc: kern/system_events.cc: kern/system_events.hh: PCEvents now schedule themselves in constructor. cpu/pc_event.hh: PCEvents now schedule themselves in the constructor. Get rid of constructor versions that don't take an address and all the schedule() methods that are now unnecessary. kern/freebsd/freebsd_system.cc: kern/freebsd/freebsd_system.hh: Use new System methods to schedule function-based events. Move FreeBSD-specific function event classes into FreebsdSystem. kern/linux/linux_system.cc: kern/linux/linux_system.hh: Use new System methods to schedule function-based events. Move Linux-specific function event classes into LinuxSystem. kern/tru64/tru64_events.hh: PCEvents now schedule themselves in constructor. Add DebugPrintfrEvent to encapsulate raw setting as new type (to work better with new System function-event method.) kern/tru64/tru64_system.cc: Use new System methods to schedule function-based events. kern/tru64/tru64_system.hh: Add DebugPrintfrEvent to encapsulate raw setting as new type (to work better with new System function-event method.) sim/system.cc: sim/system.hh: Add functions to set up function-based events, including automatically fixing up addresses to deal with optionally executed Alpha gp update prolog. --HG-- extra : convert_revision : c2cf09144297b6602afe755a34a0a2227023783f
This commit is contained in:
parent
b15a7aaf5e
commit
d60de7122d
15 changed files with 291 additions and 185 deletions
|
@ -282,8 +282,6 @@ full_system_sources = Split('''
|
||||||
kern/kernel_stats.cc
|
kern/kernel_stats.cc
|
||||||
kern/system_events.cc
|
kern/system_events.cc
|
||||||
kern/freebsd/freebsd_system.cc
|
kern/freebsd/freebsd_system.cc
|
||||||
kern/freebsd/freebsd_events.cc
|
|
||||||
kern/linux/linux_events.cc
|
|
||||||
kern/linux/linux_syscalls.cc
|
kern/linux/linux_syscalls.cc
|
||||||
kern/linux/linux_system.cc
|
kern/linux/linux_system.cc
|
||||||
kern/linux/printk.cc
|
kern/linux/printk.cc
|
||||||
|
|
|
@ -713,7 +713,6 @@ RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
|
||||||
gdb(_gdb), refcount(0)
|
gdb(_gdb), refcount(0)
|
||||||
{
|
{
|
||||||
DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
|
DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
|
||||||
schedule();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -117,8 +117,9 @@ PCEventQueue::equal_range(Addr pc)
|
||||||
return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare());
|
return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare());
|
||||||
}
|
}
|
||||||
|
|
||||||
BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del)
|
BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, Addr addr,
|
||||||
: PCEvent(q, desc), remove(del)
|
bool del)
|
||||||
|
: PCEvent(q, desc, addr), remove(del)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,8 +138,7 @@ extern "C"
|
||||||
void
|
void
|
||||||
sched_break_pc_sys(System *sys, Addr addr)
|
sched_break_pc_sys(System *sys, Addr addr)
|
||||||
{
|
{
|
||||||
PCEvent *event = new BreakPCEvent(&sys->pcEventQueue, "debug break", true);
|
new BreakPCEvent(&sys->pcEventQueue, "debug break", addr, true);
|
||||||
event->schedule(addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
|
|
@ -47,25 +47,17 @@ class PCEvent
|
||||||
Addr evpc;
|
Addr evpc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PCEvent() : queue(0), evpc(badpc) { }
|
PCEvent(PCEventQueue *q, const std::string &desc, Addr pc);
|
||||||
|
|
||||||
PCEvent(const std::string &desc)
|
|
||||||
: description(desc), queue(0), evpc(badpc) { }
|
|
||||||
|
|
||||||
PCEvent(PCEventQueue *q, Addr pc = badpc) : queue(q), evpc(pc) { }
|
|
||||||
|
|
||||||
PCEvent(PCEventQueue *q, const std::string &desc, Addr pc = badpc)
|
|
||||||
: description(desc), queue(q), evpc(pc) { }
|
|
||||||
|
|
||||||
virtual ~PCEvent() { if (queue) remove(); }
|
virtual ~PCEvent() { if (queue) remove(); }
|
||||||
|
|
||||||
|
// for DPRINTF
|
||||||
|
virtual const std::string name() const { return description; }
|
||||||
|
|
||||||
std::string descr() const { return description; }
|
std::string descr() const { return description; }
|
||||||
Addr pc() const { return evpc; }
|
Addr pc() const { return evpc; }
|
||||||
|
|
||||||
bool remove();
|
bool remove();
|
||||||
bool schedule();
|
|
||||||
bool schedule(Addr pc);
|
|
||||||
bool schedule(PCEventQueue *q, Addr pc);
|
|
||||||
virtual void process(ExecContext *xc) = 0;
|
virtual void process(ExecContext *xc) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,6 +112,14 @@ class PCEventQueue
|
||||||
void dump() const;
|
void dump() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
PCEvent::PCEvent(PCEventQueue *q, const std::string &desc, Addr pc)
|
||||||
|
: description(desc), queue(q), evpc(pc)
|
||||||
|
{
|
||||||
|
queue->schedule(this);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
PCEvent::remove()
|
PCEvent::remove()
|
||||||
{
|
{
|
||||||
|
@ -129,47 +129,14 @@ PCEvent::remove()
|
||||||
return queue->remove(this);
|
return queue->remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
|
||||||
PCEvent::schedule()
|
|
||||||
{
|
|
||||||
if (!queue || evpc == badpc)
|
|
||||||
panic("cannot schedule an uninitialized event;");
|
|
||||||
|
|
||||||
return queue->schedule(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
PCEvent::schedule(Addr pc)
|
|
||||||
{
|
|
||||||
if (evpc != badpc)
|
|
||||||
panic("cannot switch PC");
|
|
||||||
evpc = pc & ~0x3;
|
|
||||||
|
|
||||||
return schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
PCEvent::schedule(PCEventQueue *q, Addr pc)
|
|
||||||
{
|
|
||||||
if (queue)
|
|
||||||
panic("cannot switch event queues");
|
|
||||||
|
|
||||||
if (evpc != badpc)
|
|
||||||
panic("cannot switch addresses");
|
|
||||||
|
|
||||||
queue = q;
|
|
||||||
evpc = pc & ~0x3;
|
|
||||||
|
|
||||||
return schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
class BreakPCEvent : public PCEvent
|
class BreakPCEvent : public PCEvent
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
bool remove;
|
bool remove;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del = false);
|
BreakPCEvent(PCEventQueue *q, const std::string &desc, Addr addr,
|
||||||
|
bool del = false);
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -48,18 +48,13 @@ using namespace std;
|
||||||
FreebsdSystem::FreebsdSystem(Params *p)
|
FreebsdSystem::FreebsdSystem(Params *p)
|
||||||
: System(p)
|
: System(p)
|
||||||
{
|
{
|
||||||
Addr addr = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any time DELAY is called just skip the function.
|
* Any time DELAY is called just skip the function.
|
||||||
|
* Shouldn't we actually emulate the delay?
|
||||||
*/
|
*/
|
||||||
skipDelayEvent = new SkipFuncEvent(&pcEventQueue, "DELAY");
|
skipDelayEvent = addKernelFuncEvent<SkipFuncEvent>("DELAY");
|
||||||
if (kernelSymtab->findAddress("DELAY", addr))
|
skipCalibrateClocks =
|
||||||
skipDelayEvent->schedule(addr+sizeof(MachInst));
|
addKernelFuncEvent<SkipCalibrateClocksEvent>("calibrate_clocks");
|
||||||
|
|
||||||
skipCalibrateClocks = new FreebsdSkipCalibrateClocksEvent(&pcEventQueue, "calibrate_clocks");
|
|
||||||
if (kernelSymtab->findAddress("calibrate_clocks", addr))
|
|
||||||
skipCalibrateClocks->schedule(addr + sizeof(MachInst) * 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,6 +87,14 @@ FreebsdSystem::doCalibrateClocks(ExecContext *xc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FreebsdSystem::SkipCalibrateClocksEvent::process(ExecContext *xc)
|
||||||
|
{
|
||||||
|
SkipFuncEvent::process(xc);
|
||||||
|
((FreebsdSystem *)xc->system)->doCalibrateClocks(xc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdSystem)
|
BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdSystem)
|
||||||
|
|
||||||
Param<Tick> boot_cpu_frequency;
|
Param<Tick> boot_cpu_frequency;
|
||||||
|
|
|
@ -29,13 +29,22 @@
|
||||||
#ifndef __KERN_FREEBSD_FREEBSD_SYSTEM_HH__
|
#ifndef __KERN_FREEBSD_FREEBSD_SYSTEM_HH__
|
||||||
#define __KERN_FREEBSD_FREEBSD_SYSTEM_HH__
|
#define __KERN_FREEBSD_FREEBSD_SYSTEM_HH__
|
||||||
|
|
||||||
#include "kern/freebsd/freebsd_events.hh"
|
#include "kern/system_events.hh"
|
||||||
|
|
||||||
class FreebsdSystem : public System
|
class FreebsdSystem : public System
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
class SkipCalibrateClocksEvent : public SkipFuncEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SkipCalibrateClocksEvent(PCEventQueue *q, const std::string &desc,
|
||||||
|
Addr addr)
|
||||||
|
: SkipFuncEvent(q, desc, addr) {}
|
||||||
|
virtual void process(ExecContext *xc);
|
||||||
|
};
|
||||||
|
|
||||||
SkipFuncEvent *skipDelayEvent;
|
SkipFuncEvent *skipDelayEvent;
|
||||||
FreebsdSkipCalibrateClocksEvent *skipCalibrateClocks;
|
SkipCalibrateClocksEvent *skipCalibrateClocks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FreebsdSystem(Params *p);
|
FreebsdSystem(Params *p);
|
||||||
|
|
|
@ -38,12 +38,14 @@
|
||||||
#include "base/loader/symtab.hh"
|
#include "base/loader/symtab.hh"
|
||||||
#include "cpu/exec_context.hh"
|
#include "cpu/exec_context.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "kern/linux/linux_events.hh"
|
|
||||||
#include "kern/linux/linux_system.hh"
|
#include "kern/linux/linux_system.hh"
|
||||||
|
#include "kern/linux/linux_threadinfo.hh"
|
||||||
|
#include "kern/linux/printk.hh"
|
||||||
#include "mem/functional/memory_control.hh"
|
#include "mem/functional/memory_control.hh"
|
||||||
#include "mem/functional/physical.hh"
|
#include "mem/functional/physical.hh"
|
||||||
#include "sim/builder.hh"
|
#include "sim/builder.hh"
|
||||||
#include "dev/platform.hh"
|
#include "dev/platform.hh"
|
||||||
|
#include "targetarch/arguments.hh"
|
||||||
#include "targetarch/vtophys.hh"
|
#include "targetarch/vtophys.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -106,80 +108,57 @@ LinuxSystem::LinuxSystem(Params *p)
|
||||||
panic("could not find dp264_mv\n");
|
panic("could not find dp264_mv\n");
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
|
kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
|
||||||
if (kernelSymtab->findAddress("panic", addr))
|
if (!kernelPanicEvent)
|
||||||
kernelPanicEvent->schedule(addr);
|
|
||||||
else
|
|
||||||
panic("could not find kernel symbol \'panic\'");
|
panic("could not find kernel symbol \'panic\'");
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
kernelDieEvent = new BreakPCEvent(&pcEventQueue, "die if kernel");
|
kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
|
||||||
if (kernelSymtab->findAddress("die_if_kernel", addr))
|
if (!kernelDieEvent)
|
||||||
kernelDieEvent->schedule(addr);
|
|
||||||
else
|
|
||||||
panic("could not find kernel symbol \'die_if_kernel\'");
|
panic("could not find kernel symbol \'die_if_kernel\'");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any time ide_delay_50ms, calibarte_delay or
|
v * Any time ide_delay_50ms, calibarte_delay or
|
||||||
* determine_cpu_caches is called just skip the
|
* determine_cpu_caches is called just skip the
|
||||||
* function. Currently determine_cpu_caches only is used put
|
* function. Currently determine_cpu_caches only is used put
|
||||||
* information in proc, however if that changes in the future we
|
* information in proc, however if that changes in the future we
|
||||||
* will have to fill in the cache size variables appropriately.
|
* 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,
|
skipIdeDelay50msEvent =
|
||||||
"calibrate_delay");
|
addKernelFuncEvent<SkipFuncEvent>("ide_delay_50ms");
|
||||||
if (kernelSymtab->findAddress("calibrate_delay", addr)) {
|
skipDelayLoopEvent =
|
||||||
skipDelayLoopEvent->schedule(addr + 3 * sizeof(MachInst));
|
addKernelFuncEvent<SkipDelayLoopEvent>("calibrate_delay");
|
||||||
|
skipCacheProbeEvent =
|
||||||
|
addKernelFuncEvent<SkipFuncEvent>("determine_cpu_caches");
|
||||||
|
debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
|
||||||
|
idleStartEvent = addKernelFuncEvent<IdleStartEvent>("cpu_idle");
|
||||||
|
|
||||||
|
if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread)) {
|
||||||
|
printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo",
|
||||||
|
addr + sizeof(MachInst) * 6);
|
||||||
|
} else {
|
||||||
|
printThreadEvent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
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+8);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
intStartEvent = new InterruptStartEvent(&pcEventQueue, "intStartEvent");
|
|
||||||
|
|
||||||
if (params->bin_int) {
|
if (params->bin_int) {
|
||||||
if (palSymtab->findAddress("sys_int_21", addr))
|
intStartEvent = addPalFuncEvent<InterruptStartEvent>("sys_int_21");
|
||||||
intStartEvent->schedule(addr + sizeof(MachInst) * 2);
|
if (!intStartEvent)
|
||||||
else
|
|
||||||
panic("could not find symbol: sys_int_21\n");
|
panic("could not find symbol: sys_int_21\n");
|
||||||
|
|
||||||
intEndEvent = new InterruptEndEvent(&pcEventQueue, "intEndEvent");
|
intEndEvent = addPalFuncEvent<InterruptEndEvent>("rti_to_kern");
|
||||||
if (palSymtab->findAddress("rti_to_kern", addr))
|
if (!intEndEvent)
|
||||||
intEndEvent->schedule(addr) ;
|
|
||||||
else
|
|
||||||
panic("could not find symbol: rti_to_kern\n");
|
panic("could not find symbol: rti_to_kern\n");
|
||||||
|
|
||||||
intEndEvent2 = new InterruptEndEvent(&pcEventQueue, "intEndEvent2");
|
intEndEvent2 = addPalFuncEvent<InterruptEndEvent>("rti_to_user");
|
||||||
if (palSymtab->findAddress("rti_to_user", addr))
|
if (!intEndEvent2)
|
||||||
intEndEvent2->schedule(addr);
|
|
||||||
else
|
|
||||||
panic("could not find symbol: rti_to_user\n");
|
panic("could not find symbol: rti_to_user\n");
|
||||||
|
|
||||||
|
intEndEvent3 = addKernelFuncEvent<InterruptEndEvent>("do_softirq");
|
||||||
intEndEvent3 = new InterruptEndEvent(&pcEventQueue, "intEndEvent3");
|
if (!intEndEvent3)
|
||||||
if (kernelSymtab->findAddress("do_softirq", addr))
|
|
||||||
intEndEvent3->schedule(addr + sizeof(MachInst) * 2);
|
|
||||||
else
|
|
||||||
panic("could not find symbol: do_softirq\n");
|
panic("could not find symbol: do_softirq\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,6 +197,39 @@ LinuxSystem::setDelayLoop(ExecContext *xc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LinuxSystem::SkipDelayLoopEvent::process(ExecContext *xc)
|
||||||
|
{
|
||||||
|
SkipFuncEvent::process(xc);
|
||||||
|
// calculate and set loops_per_jiffy
|
||||||
|
((LinuxSystem *)xc->system)->setDelayLoop(xc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LinuxSystem::DebugPrintkEvent::process(ExecContext *xc)
|
||||||
|
{
|
||||||
|
if (DTRACE(DebugPrintf)) {
|
||||||
|
if (!raw) {
|
||||||
|
StringWrap name(xc->system->name() + ".dprintk");
|
||||||
|
DPRINTFN("");
|
||||||
|
}
|
||||||
|
|
||||||
|
AlphaArguments args(xc);
|
||||||
|
Printk(args);
|
||||||
|
SkipFuncEvent::process(xc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LinuxSystem::PrintThreadInfo::process(ExecContext *xc)
|
||||||
|
{
|
||||||
|
Linux::ThreadInfo ti(xc);
|
||||||
|
|
||||||
|
DPRINTF(Thread, "Currently Executing Thread %s, pid %d, started at: %d\n",
|
||||||
|
ti.curTaskName(), ti.curTaskPID(), ti.curTaskStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
|
BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
|
||||||
|
|
||||||
Param<Tick> boot_cpu_frequency;
|
Param<Tick> boot_cpu_frequency;
|
||||||
|
|
|
@ -32,10 +32,6 @@
|
||||||
class ExecContext;
|
class ExecContext;
|
||||||
|
|
||||||
class BreakPCEvent;
|
class BreakPCEvent;
|
||||||
class DebugPrintkEvent;
|
|
||||||
class BreakPCEvent;
|
|
||||||
class LinuxSkipDelayLoopEvent;
|
|
||||||
class SkipFuncEvent;
|
|
||||||
class IdleStartEvent;
|
class IdleStartEvent;
|
||||||
class PrintThreadInfo;
|
class PrintThreadInfo;
|
||||||
|
|
||||||
|
@ -47,6 +43,34 @@ class PrintThreadInfo;
|
||||||
class LinuxSystem : public System
|
class LinuxSystem : public System
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
class SkipDelayLoopEvent : public SkipFuncEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
|
: SkipFuncEvent(q, desc, addr) {}
|
||||||
|
virtual void process(ExecContext *xc);
|
||||||
|
};
|
||||||
|
|
||||||
|
class DebugPrintkEvent : public SkipFuncEvent
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool raw;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DebugPrintkEvent(PCEventQueue *q, const std::string &desc, Addr addr,
|
||||||
|
bool r = false)
|
||||||
|
: SkipFuncEvent(q, desc, addr), raw(r) {}
|
||||||
|
virtual void process(ExecContext *xc);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PrintThreadInfo : public PCEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
|
: PCEvent(q, desc, addr) {}
|
||||||
|
virtual void process(ExecContext *xc);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Addresses defining where the kernel bootloader places various
|
* Addresses defining where the kernel bootloader places various
|
||||||
* elements. Details found in include/asm-alpha/system.h
|
* elements. Details found in include/asm-alpha/system.h
|
||||||
|
@ -94,7 +118,7 @@ class LinuxSystem : public System
|
||||||
* Skip calculate_delay_loop() rather than waiting for this to be
|
* Skip calculate_delay_loop() rather than waiting for this to be
|
||||||
* calculated
|
* calculated
|
||||||
*/
|
*/
|
||||||
LinuxSkipDelayLoopEvent *skipDelayLoopEvent;
|
SkipDelayLoopEvent *skipDelayLoopEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event to print information about thread switches if the trace flag
|
* Event to print information about thread switches if the trace flag
|
||||||
|
|
|
@ -47,8 +47,9 @@ SkipFuncEvent::process(ExecContext *xc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Stats::MainBin *bin)
|
FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Addr addr,
|
||||||
: PCEvent(q, desc), _name(desc), mybin(bin)
|
Stats::MainBin *bin)
|
||||||
|
: PCEvent(q, desc, addr), _name(desc), mybin(bin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,20 +29,24 @@
|
||||||
#ifndef __SYSTEM_EVENTS_HH__
|
#ifndef __SYSTEM_EVENTS_HH__
|
||||||
#define __SYSTEM_EVENTS_HH__
|
#define __SYSTEM_EVENTS_HH__
|
||||||
|
|
||||||
|
#include "cpu/pc_event.hh"
|
||||||
|
|
||||||
class System;
|
class System;
|
||||||
|
|
||||||
class SkipFuncEvent : public PCEvent
|
class SkipFuncEvent : public PCEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SkipFuncEvent(PCEventQueue *q, const std::string &desc)
|
SkipFuncEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
: PCEvent(q, desc) {}
|
: PCEvent(q, desc, addr)
|
||||||
|
{}
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FnEvent : public PCEvent
|
class FnEvent : public PCEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FnEvent(PCEventQueue *q, const std::string &desc, Stats::MainBin *bin);
|
FnEvent(PCEventQueue *q, const std::string &desc, Addr addr,
|
||||||
|
Stats::MainBin *bin);
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
std::string myname() const { return _name; }
|
std::string myname() const { return _name; }
|
||||||
|
|
||||||
|
@ -53,12 +57,9 @@ class FnEvent : public PCEvent
|
||||||
|
|
||||||
class IdleStartEvent : public PCEvent
|
class IdleStartEvent : public PCEvent
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
System *system;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IdleStartEvent(PCEventQueue *q, const std::string &desc, System *sys)
|
IdleStartEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
: PCEvent(q, desc), system(sys)
|
: PCEvent(q, desc, addr)
|
||||||
{}
|
{}
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
};
|
};
|
||||||
|
@ -66,8 +67,8 @@ class IdleStartEvent : public PCEvent
|
||||||
class InterruptStartEvent : public PCEvent
|
class InterruptStartEvent : public PCEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InterruptStartEvent(PCEventQueue *q, const std::string &desc)
|
InterruptStartEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
: PCEvent(q, desc)
|
: PCEvent(q, desc, addr)
|
||||||
{}
|
{}
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
};
|
};
|
||||||
|
@ -75,8 +76,8 @@ class InterruptStartEvent : public PCEvent
|
||||||
class InterruptEndEvent : public PCEvent
|
class InterruptEndEvent : public PCEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InterruptEndEvent(PCEventQueue *q, const std::string &desc)
|
InterruptEndEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
: PCEvent(q, desc)
|
: PCEvent(q, desc, addr)
|
||||||
{}
|
{}
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,16 +39,16 @@ class ExecContext;
|
||||||
class BadAddrEvent : public SkipFuncEvent
|
class BadAddrEvent : public SkipFuncEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BadAddrEvent(PCEventQueue *q, const std::string &desc)
|
BadAddrEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
: SkipFuncEvent(q, desc) {}
|
: SkipFuncEvent(q, desc, addr) {}
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PrintfEvent : public PCEvent
|
class PrintfEvent : public PCEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PrintfEvent(PCEventQueue *q, const std::string &desc)
|
PrintfEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
: PCEvent(q, desc) {}
|
: PCEvent(q, desc, addr) {}
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,16 +58,25 @@ class DebugPrintfEvent : public PCEvent
|
||||||
bool raw;
|
bool raw;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DebugPrintfEvent(PCEventQueue *q, const std::string &desc, bool r = false)
|
DebugPrintfEvent(PCEventQueue *q, const std::string &desc, Addr addr,
|
||||||
: PCEvent(q, desc), raw(r) {}
|
bool r = false)
|
||||||
|
: PCEvent(q, desc, addr), raw(r) {}
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DebugPrintfrEvent : public DebugPrintfEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DebugPrintfrEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
|
: DebugPrintfEvent(q, desc, addr, true)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
class DumpMbufEvent : public PCEvent
|
class DumpMbufEvent : public PCEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DumpMbufEvent(PCEventQueue *q, const std::string &desc)
|
DumpMbufEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
: PCEvent(q, desc) {}
|
: PCEvent(q, desc, addr) {}
|
||||||
virtual void process(ExecContext *xc);
|
virtual void process(ExecContext *xc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -55,47 +55,25 @@ Tru64System::Tru64System(Tru64System::Params *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
|
kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
|
||||||
if (kernelSymtab->findAddress("panic", addr))
|
if (!kernelPanicEvent)
|
||||||
kernelPanicEvent->schedule(addr);
|
|
||||||
else
|
|
||||||
panic("could not find kernel symbol \'panic\'");
|
panic("could not find kernel symbol \'panic\'");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
badaddrEvent = new BadAddrEvent(&pcEventQueue, "badaddr");
|
badaddrEvent = addKernelFuncEvent<BadAddrEvent>("badaddr");
|
||||||
if (kernelSymtab->findAddress("badaddr", addr))
|
if (!badaddrEvent)
|
||||||
badaddrEvent->schedule(addr);
|
|
||||||
else
|
|
||||||
panic("could not find kernel symbol \'badaddr\'");
|
panic("could not find kernel symbol \'badaddr\'");
|
||||||
|
|
||||||
skipPowerStateEvent = new SkipFuncEvent(&pcEventQueue,
|
skipPowerStateEvent =
|
||||||
"tl_v48_capture_power_state");
|
addKernelFuncEvent<SkipFuncEvent>("tl_v48_capture_power_state");
|
||||||
if (kernelSymtab->findAddress("tl_v48_capture_power_state", addr))
|
skipScavengeBootEvent =
|
||||||
skipPowerStateEvent->schedule(addr);
|
addKernelFuncEvent<SkipFuncEvent>("pmap_scavenge_boot");
|
||||||
|
|
||||||
skipScavengeBootEvent = new SkipFuncEvent(&pcEventQueue,
|
|
||||||
"pmap_scavenge_boot");
|
|
||||||
if (kernelSymtab->findAddress("pmap_scavenge_boot", addr))
|
|
||||||
skipScavengeBootEvent->schedule(addr);
|
|
||||||
|
|
||||||
#if TRACING_ON
|
#if TRACING_ON
|
||||||
printfEvent = new PrintfEvent(&pcEventQueue, "printf");
|
printfEvent = addKernelFuncEvent<PrintfEvent>("printf");
|
||||||
if (kernelSymtab->findAddress("printf", addr))
|
debugPrintfEvent = addKernelFuncEvent<DebugPrintfEvent>("m5printf");
|
||||||
printfEvent->schedule(addr);
|
debugPrintfrEvent = addKernelFuncEvent<DebugPrintfrEvent>("m5printfr");
|
||||||
|
dumpMbufEvent = addKernelFuncEvent<DumpMbufEvent>("m5_dump_mbuf");
|
||||||
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,8 @@ class Tru64System : public System
|
||||||
SkipFuncEvent *skipPowerStateEvent;
|
SkipFuncEvent *skipPowerStateEvent;
|
||||||
SkipFuncEvent *skipScavengeBootEvent;
|
SkipFuncEvent *skipScavengeBootEvent;
|
||||||
PrintfEvent *printfEvent;
|
PrintfEvent *printfEvent;
|
||||||
DebugPrintfEvent *debugPrintfEvent;
|
DebugPrintfEvent *debugPrintfEvent;
|
||||||
DebugPrintfEvent *debugPrintfrEvent;
|
DebugPrintfrEvent *debugPrintfrEvent;
|
||||||
DumpMbufEvent *dumpMbufEvent;
|
DumpMbufEvent *dumpMbufEvent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -124,9 +124,7 @@ System::System(Params *p)
|
||||||
|
|
||||||
Addr addr = 0;
|
Addr addr = 0;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
|
consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic");
|
||||||
if (consoleSymtab->findAddress("panic", addr))
|
|
||||||
consolePanicEvent->schedule(addr);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -180,6 +178,65 @@ System::~System()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function fixes up addresses that are used to match PCs for
|
||||||
|
* hooking simulator events on to target function executions.
|
||||||
|
*
|
||||||
|
* Alpha binaries may have multiple global offset table (GOT)
|
||||||
|
* sections. A function that uses the GOT starts with a
|
||||||
|
* two-instruction prolog which sets the global pointer (gp == r29) to
|
||||||
|
* the appropriate GOT section. The proper gp value is calculated
|
||||||
|
* based on the function address, which must be passed by the caller
|
||||||
|
* in the procedure value register (pv aka t12 == r27). This sequence
|
||||||
|
* looks like the following:
|
||||||
|
*
|
||||||
|
* opcode Ra Rb offset
|
||||||
|
* ldah gp,X(pv) 09 29 27 X
|
||||||
|
* lda gp,Y(gp) 08 29 29 Y
|
||||||
|
*
|
||||||
|
* for some constant offsets X and Y. The catch is that the linker
|
||||||
|
* (or maybe even the compiler, I'm not sure) may recognize that the
|
||||||
|
* caller and callee are using the same GOT section, making this
|
||||||
|
* prolog redundant, and modify the call target to skip these
|
||||||
|
* instructions. If we check for execution of the first instruction
|
||||||
|
* of a function (the one the symbol points to) to detect when to skip
|
||||||
|
* it, we'll miss all these modified calls. It might work to
|
||||||
|
* unconditionally check for the third instruction, but not all
|
||||||
|
* functions have this prolog, and there's some chance that those
|
||||||
|
* first two instructions could have undesired consequences. So we do
|
||||||
|
* the Right Thing and pattern-match the first two instructions of the
|
||||||
|
* function to decide where to patch.
|
||||||
|
*
|
||||||
|
* Eventually this code should be moved into an ISA-specific file.
|
||||||
|
*/
|
||||||
|
Addr
|
||||||
|
System::fixFuncEventAddr(Addr addr)
|
||||||
|
{
|
||||||
|
// mask for just the opcode, Ra, and Rb fields (not the offset)
|
||||||
|
const uint32_t inst_mask = 0xffff0000;
|
||||||
|
// ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
|
||||||
|
const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
|
||||||
|
// lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
|
||||||
|
const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
|
||||||
|
// instruction size
|
||||||
|
const int sz = sizeof(uint32_t);
|
||||||
|
|
||||||
|
Addr paddr = vtophys(physmem, addr);
|
||||||
|
uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz);
|
||||||
|
uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz);
|
||||||
|
|
||||||
|
if ((i1 & inst_mask) == gp_ldah_pattern &&
|
||||||
|
(i2 & inst_mask) == gp_lda_pattern) {
|
||||||
|
Addr new_addr = addr + 2*sz;
|
||||||
|
DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
|
||||||
|
return new_addr;
|
||||||
|
} else {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
System::setAlphaAccess(Addr access)
|
System::setAlphaAccess(Addr access)
|
||||||
{
|
{
|
||||||
|
@ -197,6 +254,7 @@ System::setAlphaAccess(Addr access)
|
||||||
panic("could not find m5AlphaAccess\n");
|
panic("could not find m5AlphaAccess\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
System::breakpoint()
|
System::breakpoint()
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
|
#include "base/loader/symtab.hh"
|
||||||
#include "cpu/pc_event.hh"
|
#include "cpu/pc_event.hh"
|
||||||
#include "kern/system_events.hh"
|
#include "kern/system_events.hh"
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
|
@ -45,7 +46,6 @@ class ObjectFile;
|
||||||
class PhysicalMemory;
|
class PhysicalMemory;
|
||||||
class Platform;
|
class Platform;
|
||||||
class RemoteGDB;
|
class RemoteGDB;
|
||||||
class SymbolTable;
|
|
||||||
namespace Kernel { class Binning; }
|
namespace Kernel { class Binning; }
|
||||||
|
|
||||||
class System : public SimObject
|
class System : public SimObject
|
||||||
|
@ -68,7 +68,7 @@ class System : public SimObject
|
||||||
return numcpus;
|
return numcpus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** kernel Symbol table */
|
/** kernel symbol table */
|
||||||
SymbolTable *kernelSymtab;
|
SymbolTable *kernelSymtab;
|
||||||
|
|
||||||
/** console symbol table */
|
/** console symbol table */
|
||||||
|
@ -102,6 +102,53 @@ class System : public SimObject
|
||||||
BreakPCEvent *consolePanicEvent;
|
BreakPCEvent *consolePanicEvent;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix up an address used to match PCs for hooking simulator
|
||||||
|
* events on to target function executions. See comment in
|
||||||
|
* system.cc for details.
|
||||||
|
*/
|
||||||
|
Addr fixFuncEventAddr(Addr addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a function-based event to the given function, to be looked
|
||||||
|
* up in the specified symbol table.
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
T *System::addFuncEvent(SymbolTable *symtab, const char *lbl)
|
||||||
|
{
|
||||||
|
Addr addr;
|
||||||
|
|
||||||
|
if (symtab->findAddress(lbl, addr)) {
|
||||||
|
T *ev = new T(&pcEventQueue, lbl, fixFuncEventAddr(addr));
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add a function-based event to kernel code. */
|
||||||
|
template <class T>
|
||||||
|
T *System::addKernelFuncEvent(const char *lbl)
|
||||||
|
{
|
||||||
|
return addFuncEvent<T>(kernelSymtab, lbl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add a function-based event to PALcode. */
|
||||||
|
template <class T>
|
||||||
|
T *System::addPalFuncEvent(const char *lbl)
|
||||||
|
{
|
||||||
|
return addFuncEvent<T>(palSymtab, lbl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add a function-based event to the console code. */
|
||||||
|
template <class T>
|
||||||
|
T *System::addConsoleFuncEvent(const char *lbl)
|
||||||
|
{
|
||||||
|
return addFuncEvent<T>(consoleSymtab, lbl);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<RemoteGDB *> remoteGDB;
|
std::vector<RemoteGDB *> remoteGDB;
|
||||||
std::vector<GDBListener *> gdbListen;
|
std::vector<GDBListener *> gdbListen;
|
||||||
|
|
Loading…
Reference in a new issue