Add functions to System object to set up function-based events,
authorSteve Reinhardt <stever@eecs.umich.edu>
Sat, 24 Sep 2005 18:20:29 +0000 (14:20 -0400)
committerSteve Reinhardt <stever@eecs.umich.edu>
Sat, 24 Sep 2005 18:20:29 +0000 (14:20 -0400)
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

15 files changed:
SConscript
base/remote_gdb.cc
cpu/pc_event.cc
cpu/pc_event.hh
kern/freebsd/freebsd_system.cc
kern/freebsd/freebsd_system.hh
kern/linux/linux_system.cc
kern/linux/linux_system.hh
kern/system_events.cc
kern/system_events.hh
kern/tru64/tru64_events.hh
kern/tru64/tru64_system.cc
kern/tru64/tru64_system.hh
sim/system.cc
sim/system.hh

index 2cbc96dda02d89aa01c59b82f44ee5d60ebc0515..4e2347431e33400720008691ce811cd1a454dfe9 100644 (file)
@@ -282,8 +282,6 @@ full_system_sources = Split('''
        kern/kernel_stats.cc
        kern/system_events.cc
        kern/freebsd/freebsd_system.cc
-       kern/freebsd/freebsd_events.cc
-       kern/linux/linux_events.cc
        kern/linux/linux_syscalls.cc
        kern/linux/linux_system.cc
        kern/linux/printk.cc
index 17331fcd9b2776182ba5246d98429e16a228dbdc..3af73179a9bbab380cb13457c5905d8e0e9ca9b1 100644 (file)
@@ -713,7 +713,6 @@ RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
       gdb(_gdb), refcount(0)
 {
     DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
-    schedule();
 }
 
 void
index c3bb3dbe6c5519183eba7ed073c0be10e11f1bd5..83fbc3e2d776eeb4e961a29ea829ab17def42a48 100644 (file)
@@ -117,8 +117,9 @@ PCEventQueue::equal_range(Addr pc)
     return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare());
 }
 
-BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del)
-    : PCEvent(q, desc), remove(del)
+BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, Addr addr,
+                           bool del)
+    : PCEvent(q, desc, addr), remove(del)
 {
 }
 
@@ -137,8 +138,7 @@ extern "C"
 void
 sched_break_pc_sys(System *sys, Addr addr)
 {
-    PCEvent *event = new BreakPCEvent(&sys->pcEventQueue, "debug break", true);
-    event->schedule(addr);
+    new BreakPCEvent(&sys->pcEventQueue, "debug break", addr, true);
 }
 
 extern "C"
index 65ef0a088defd269138f33338ec1c4409d80a55a..7fa3902ccd272ad017a892f3d3409f7ba6981730 100644 (file)
@@ -47,25 +47,17 @@ class PCEvent
     Addr evpc;
 
   public:
-    PCEvent() : queue(0), evpc(badpc) { }
-
-    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) { }
+    PCEvent(PCEventQueue *q, const std::string &desc, Addr pc);
 
     virtual ~PCEvent() { if (queue) remove(); }
 
+    // for DPRINTF
+    virtual const std::string name() const { return description; }
+
     std::string descr() const { return description; }
     Addr pc() const { return evpc; }
 
     bool remove();
-    bool schedule();
-    bool schedule(Addr pc);
-    bool schedule(PCEventQueue *q, Addr pc);
     virtual void process(ExecContext *xc) = 0;
 };
 
@@ -120,47 +112,21 @@ class PCEventQueue
     void dump() const;
 };
 
-inline bool
-PCEvent::remove()
-{
-    if (!queue)
-        panic("cannot remove an uninitialized event;");
-
-    return queue->remove(this);
-}
 
-inline bool
-PCEvent::schedule()
+inline
+PCEvent::PCEvent(PCEventQueue *q, const std::string &desc, Addr pc)
+    : description(desc), queue(q), evpc(pc)
 {
-    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();
+    queue->schedule(this);
 }
 
 inline bool
-PCEvent::schedule(PCEventQueue *q, Addr pc)
+PCEvent::remove()
 {
-    if (queue)
-        panic("cannot switch event queues");
-
-    if (evpc != badpc)
-        panic("cannot switch addresses");
-
-    queue = q;
-    evpc = pc & ~0x3;
+    if (!queue)
+        panic("cannot remove an uninitialized event;");
 
-    return schedule();
+    return queue->remove(this);
 }
 
 class BreakPCEvent : public PCEvent
@@ -169,7 +135,8 @@ class BreakPCEvent : public PCEvent
     bool remove;
 
   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);
 };
 
index 5e0ce113bbe5daec4664708f4e9bd12a3890ffbd..283713d40d02286744908dc2112a5da251735dac 100644 (file)
@@ -48,18 +48,13 @@ using namespace std;
 FreebsdSystem::FreebsdSystem(Params *p)
     : System(p)
 {
-    Addr addr = 0;
-
     /**
      * Any time DELAY is called just skip the function.
+     * Shouldn't we actually emulate the delay?
      */
-    skipDelayEvent = new SkipFuncEvent(&pcEventQueue, "DELAY");
-    if (kernelSymtab->findAddress("DELAY", addr))
-        skipDelayEvent->schedule(addr+sizeof(MachInst));
-
-    skipCalibrateClocks = new FreebsdSkipCalibrateClocksEvent(&pcEventQueue, "calibrate_clocks");
-    if (kernelSymtab->findAddress("calibrate_clocks", addr))
-        skipCalibrateClocks->schedule(addr + sizeof(MachInst) * 2);
+    skipDelayEvent = addKernelFuncEvent<SkipFuncEvent>("DELAY");
+    skipCalibrateClocks =
+        addKernelFuncEvent<SkipCalibrateClocksEvent>("calibrate_clocks");
 }
 
 
@@ -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)
 
     Param<Tick> boot_cpu_frequency;
index 6429b569050f9d7d70996308178e8fa08af1c7f7..ecb842ec619c81d878d15817f18f516b0089ff59 100644 (file)
 #ifndef __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
 {
   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;
-    FreebsdSkipCalibrateClocksEvent *skipCalibrateClocks;
+    SkipCalibrateClocksEvent *skipCalibrateClocks;
 
   public:
     FreebsdSystem(Params *p);
index e3b9990c5b5f660661fe4a7e2b90aea1f8144047..addce0389a7848f3da3a66ae11e880ec9061de32 100644 (file)
 #include "base/loader/symtab.hh"
 #include "cpu/exec_context.hh"
 #include "cpu/base.hh"
-#include "kern/linux/linux_events.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/physical.hh"
 #include "sim/builder.hh"
 #include "dev/platform.hh"
+#include "targetarch/arguments.hh"
 #include "targetarch/vtophys.hh"
 
 using namespace std;
@@ -106,80 +108,57 @@ LinuxSystem::LinuxSystem(Params *p)
         panic("could not find dp264_mv\n");
 
 #ifndef NDEBUG
-    kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
-    if (kernelSymtab->findAddress("panic", addr))
-        kernelPanicEvent->schedule(addr);
-    else
+    kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
+    if (!kernelPanicEvent)
         panic("could not find kernel symbol \'panic\'");
+
 #if 0
-    kernelDieEvent = new BreakPCEvent(&pcEventQueue, "die if kernel");
-    if (kernelSymtab->findAddress("die_if_kernel", addr))
-        kernelDieEvent->schedule(addr);
-    else
+    kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
+    if (!kernelDieEvent)
         panic("could not find kernel symbol \'die_if_kernel\'");
 #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
      * 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 + 3 * 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+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");
+    skipIdeDelay50msEvent =
+        addKernelFuncEvent<SkipFuncEvent>("ide_delay_50ms");
+    skipDelayLoopEvent =
+        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;
+    }
 
     if (params->bin_int) {
-        if (palSymtab->findAddress("sys_int_21", addr))
-            intStartEvent->schedule(addr + sizeof(MachInst) * 2);
-        else
+        intStartEvent = addPalFuncEvent<InterruptStartEvent>("sys_int_21");
+        if (!intStartEvent)
             panic("could not find symbol: sys_int_21\n");
 
-        intEndEvent = new InterruptEndEvent(&pcEventQueue, "intEndEvent");
-        if (palSymtab->findAddress("rti_to_kern", addr))
-            intEndEvent->schedule(addr) ;
-        else
+        intEndEvent = addPalFuncEvent<InterruptEndEvent>("rti_to_kern");
+        if (!intEndEvent)
             panic("could not find symbol: rti_to_kern\n");
 
-        intEndEvent2 = new InterruptEndEvent(&pcEventQueue, "intEndEvent2");
-        if (palSymtab->findAddress("rti_to_user", addr))
-            intEndEvent2->schedule(addr);
-        else
+        intEndEvent2 = addPalFuncEvent<InterruptEndEvent>("rti_to_user");
+        if (!intEndEvent2)
             panic("could not find symbol: rti_to_user\n");
 
-
-        intEndEvent3 = new InterruptEndEvent(&pcEventQueue, "intEndEvent3");
-        if (kernelSymtab->findAddress("do_softirq", addr))
-            intEndEvent3->schedule(addr + sizeof(MachInst) * 2);
-        else
+        intEndEvent3 = addKernelFuncEvent<InterruptEndEvent>("do_softirq");
+        if (!intEndEvent3)
             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)
 
     Param<Tick> boot_cpu_frequency;
index 2ddddbc1a06be24c74d8e3c52cdfe005e428d08a..f883bef9374d4fa911bb7a0dcc94173d3a35bbb2 100644 (file)
 class ExecContext;
 
 class BreakPCEvent;
-class DebugPrintkEvent;
-class BreakPCEvent;
-class LinuxSkipDelayLoopEvent;
-class SkipFuncEvent;
 class IdleStartEvent;
 class PrintThreadInfo;
 
@@ -47,6 +43,34 @@ class PrintThreadInfo;
 class LinuxSystem : public System
 {
   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
      * 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
      * calculated
      */
-    LinuxSkipDelayLoopEvent *skipDelayLoopEvent;
+    SkipDelayLoopEvent *skipDelayLoopEvent;
 
     /**
      * Event to print information about thread switches if the trace flag
index d5c0d242a19bfa2042ab031c8caa54d8c780f000..ba3c9274a7d15c95c647386404680d3510a3c9d1 100644 (file)
@@ -47,8 +47,9 @@ SkipFuncEvent::process(ExecContext *xc)
 }
 
 
-FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Stats::MainBin *bin)
-    : PCEvent(q, desc), _name(desc), mybin(bin)
+FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Addr addr,
+                 Stats::MainBin *bin)
+    : PCEvent(q, desc, addr), _name(desc), mybin(bin)
 {
 }
 
index 94f6efebaac6d4c6a752c0ec306f55932a8d3ed1..246140a09567e579984d805a678f610b93c39670 100644 (file)
 #ifndef __SYSTEM_EVENTS_HH__
 #define __SYSTEM_EVENTS_HH__
 
+#include "cpu/pc_event.hh"
+
 class System;
 
 class SkipFuncEvent : public PCEvent
 {
   public:
-    SkipFuncEvent(PCEventQueue *q, const std::string &desc)
-        : PCEvent(q, desc) {}
+    SkipFuncEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+        : PCEvent(q, desc, addr)
+    {}
     virtual void process(ExecContext *xc);
 };
 
 class FnEvent : public PCEvent
 {
   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);
     std::string myname() const { return _name; }
 
@@ -53,12 +57,9 @@ class FnEvent : public PCEvent
 
 class IdleStartEvent : public PCEvent
 {
-  private:
-    System *system;
-
   public:
-    IdleStartEvent(PCEventQueue *q, const std::string &desc, System *sys)
-        : PCEvent(q, desc), system(sys)
+    IdleStartEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+        : PCEvent(q, desc, addr)
     {}
     virtual void process(ExecContext *xc);
 };
@@ -66,8 +67,8 @@ class IdleStartEvent : public PCEvent
 class InterruptStartEvent : public PCEvent
 {
   public:
-    InterruptStartEvent(PCEventQueue *q, const std::string &desc)
-        : PCEvent(q, desc)
+    InterruptStartEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+        : PCEvent(q, desc, addr)
     {}
     virtual void process(ExecContext *xc);
 };
@@ -75,8 +76,8 @@ class InterruptStartEvent : public PCEvent
 class InterruptEndEvent : public PCEvent
 {
   public:
-    InterruptEndEvent(PCEventQueue *q, const std::string &desc)
-        : PCEvent(q, desc)
+    InterruptEndEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+        : PCEvent(q, desc, addr)
     {}
     virtual void process(ExecContext *xc);
 };
index d3b6d6f8cb06602fb5f00d6ee2124b976c7781f6..9b5bcfea2c6c49b005e94227f27bf09aa66ea8be 100644 (file)
@@ -39,16 +39,16 @@ class ExecContext;
 class BadAddrEvent : public SkipFuncEvent
 {
   public:
-    BadAddrEvent(PCEventQueue *q, const std::string &desc)
-        : SkipFuncEvent(q, desc) {}
+    BadAddrEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+        : SkipFuncEvent(q, desc, addr) {}
     virtual void process(ExecContext *xc);
 };
 
 class PrintfEvent : public PCEvent
 {
   public:
-    PrintfEvent(PCEventQueue *q, const std::string &desc)
-        : PCEvent(q, desc) {}
+    PrintfEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+        : PCEvent(q, desc, addr) {}
     virtual void process(ExecContext *xc);
 };
 
@@ -58,16 +58,25 @@ class DebugPrintfEvent : public PCEvent
     bool raw;
 
   public:
-    DebugPrintfEvent(PCEventQueue *q, const std::string &desc, bool r = false)
-        : PCEvent(q, desc), raw(r) {}
+    DebugPrintfEvent(PCEventQueue *q, const std::string &desc, Addr addr,
+                     bool r = false)
+        : PCEvent(q, desc, addr), raw(r) {}
     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
 {
   public:
-    DumpMbufEvent(PCEventQueue *q, const std::string &desc)
-        : PCEvent(q, desc) {}
+    DumpMbufEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+        : PCEvent(q, desc, addr) {}
     virtual void process(ExecContext *xc);
 };
 
index d4b056c622dc018f876c4a842d16da1ef38d6f83..f65293474b660ecf67c77ea901a6c22a97411076 100644 (file)
@@ -55,47 +55,25 @@ Tru64System::Tru64System(Tru64System::Params *p)
     }
 
 #ifdef DEBUG
-    kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
-    if (kernelSymtab->findAddress("panic", addr))
-        kernelPanicEvent->schedule(addr);
-    else
+    kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
+    if (!kernelPanicEvent)
         panic("could not find kernel symbol \'panic\'");
 #endif
 
-    badaddrEvent = new BadAddrEvent(&pcEventQueue, "badaddr");
-    if (kernelSymtab->findAddress("badaddr", addr))
-        badaddrEvent->schedule(addr);
-    else
+    badaddrEvent = addKernelFuncEvent<BadAddrEvent>("badaddr");
+    if (!badaddrEvent)
         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);
+    skipPowerStateEvent =
+        addKernelFuncEvent<SkipFuncEvent>("tl_v48_capture_power_state");
+    skipScavengeBootEvent =
+        addKernelFuncEvent<SkipFuncEvent>("pmap_scavenge_boot");
 
 #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);
+    printfEvent = addKernelFuncEvent<PrintfEvent>("printf");
+    debugPrintfEvent = addKernelFuncEvent<DebugPrintfEvent>("m5printf");
+    debugPrintfrEvent = addKernelFuncEvent<DebugPrintfrEvent>("m5printfr");
+    dumpMbufEvent = addKernelFuncEvent<DumpMbufEvent>("m5_dump_mbuf");
 #endif
 }
 
index 290b44230eb3d0a21df4195c39d0e351054c1a47..a9077e112c7cb89a53e4801b1b40d8e8dd7b3ef8 100644 (file)
@@ -54,8 +54,8 @@ class Tru64System : public System
     SkipFuncEvent *skipPowerStateEvent;
     SkipFuncEvent *skipScavengeBootEvent;
     PrintfEvent *printfEvent;
-    DebugPrintfEvent *debugPrintfEvent;
-    DebugPrintfEvent *debugPrintfrEvent;
+    DebugPrintfEvent  *debugPrintfEvent;
+    DebugPrintfrEvent *debugPrintfrEvent;
     DumpMbufEvent *dumpMbufEvent;
 
   public:
index 3da92c44734d4463f922be9b7ff49e20a2533de1..e67cae3338dd27e85263ff6be5cc4b533efc4f49 100644 (file)
@@ -124,9 +124,7 @@ System::System(Params *p)
 
     Addr addr = 0;
 #ifdef DEBUG
-    consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
-    if (consoleSymtab->findAddress("panic", addr))
-        consolePanicEvent->schedule(addr);
+    consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic");
 #endif
 
     /**
@@ -180,6 +178,65 @@ System::~System()
 #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
 System::setAlphaAccess(Addr access)
 {
@@ -197,6 +254,7 @@ System::setAlphaAccess(Addr access)
         panic("could not find m5AlphaAccess\n");
 }
 
+
 bool
 System::breakpoint()
 {
index 870805e4c9402c4a9054cb10baada631ad219f44..c4ecc9458577344be6e399c3a7017aca0e018952 100644 (file)
@@ -33,6 +33,7 @@
 #include <vector>
 
 #include "base/statistics.hh"
+#include "base/loader/symtab.hh"
 #include "cpu/pc_event.hh"
 #include "kern/system_events.hh"
 #include "sim/sim_object.hh"
@@ -45,7 +46,6 @@ class ObjectFile;
 class PhysicalMemory;
 class Platform;
 class RemoteGDB;
-class SymbolTable;
 namespace Kernel { class Binning; }
 
 class System : public SimObject
@@ -68,7 +68,7 @@ class System : public SimObject
         return numcpus;
     }
 
-    /** kernel Symbol table */
+    /** kernel symbol table */
     SymbolTable *kernelSymtab;
 
     /** console symbol table */
@@ -102,6 +102,53 @@ class System : public SimObject
     BreakPCEvent *consolePanicEvent;
 #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:
     std::vector<RemoteGDB *> remoteGDB;
     std::vector<GDBListener *> gdbListen;