Added single stepping for gem5, which is necessary to periodically check for events like interrupts.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1734 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
friemel
2012-10-10 14:26:50 +00:00
parent 15def480d9
commit 6e1a85d3bf
9 changed files with 178 additions and 45 deletions

View File

@ -18,7 +18,7 @@ elseif(BUILD_GEM5)
SimulatorController.cc
perf/BreakpointBuffer.cc
gem5/Gem5Controller.cc
gem5/Gem5PCEvent.cc
gem5/Gem5PCEvents.cc
)
elseif(BUILD_OVP)
set(SRCS

View File

@ -1,16 +1,116 @@
#include "FailGem5Device.hh"
#include "FailGem5Device.hpp"
#include "debug/Fail.hh"
#include "sim/system.hh"
#include "arch/arm/decoder.hh"
#include "cpu/simple/base.hh"
#include "../SALInst.hpp"
#include "Gem5PCEvents.hpp"
#include <bitset>
FailGem5Device::FailGem5Device(Params *p)
: BasicPioDevice(p)
{
pioSize = 0x60;
}
void FailGem5Device::startup()
{
// TODO: Find a better way/position to start single stepping.
// It's not possible to fetch the instruction at Adress 0x0
m_BreakpointNotTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, 0x80000000);
fail::simulator.startup();
}
void FailGem5Device::activateSingleStepMode()
{
setNextBreakpoints(sys->getThreadContext(0));
}
void FailGem5Device::deactivateSingleStepMode()
{
clearBreakpoints();
}
void FailGem5Device::setNextBreakpoints(ThreadContext *tc)
{
clearBreakpoints();
// Get the instruction at the current program counter
MachInst inst;
PCState pc = tc->pcState();
tc->getVirtProxy().readBlob(pc.pc(), (uint8_t*)&inst, sizeof(MachInst));
// Decode the instruction
ArmISA::Decoder* decoder = tc->getDecoderPtr();
BaseSimpleCPU* cpu = dynamic_cast<BaseSimpleCPU*>(tc->getCpuPtr());
Addr fetchPC = (pc.pc() & cpu->PCMask) + cpu->fetchOffset;
decoder->moreBytes(pc, fetchPC, inst);
StaticInstPtr si = decoder->decode(pc);
// Set breakpoints
// First breakpoint is always the next pc
// FIXME: Doesn't work properly in Thumb or Thumb2 mode
m_BreakpointNotTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, pc.npc());
// Second breakpoint will only be set if there is a possible change in control flow
DPRINTF(Fail, "Instruction Name: %s\n", si->getName());
if(si->getName().compare("bx") == 0)
{
DPRINTF(Fail, "BX instruction\n");
Addr target = tc->readIntReg(si->machInst.rm);
m_BreakpointTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, target);
return;
}
// Check for a pop instruction with the pc as target
if(si->getName().compare("ldmstm") == 0)
{
std::bitset<16> regs(si->machInst.regList);
if(regs.test(15)) // Bit 15 = pc
{
DPRINTF(Fail, "LDMSTM with pc as target\n");
Addr mem = tc->readIntReg(si->machInst.rn) + 4*(regs.count()-1);
Addr target;
tc->getVirtProxy().readBlob(mem, (uint8_t*)&target, sizeof(Addr));
DPRINTF(Fail, "Value loaded into pc: %x\n", target);
m_BreakpointTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, target);
}
return;
}
PCState bpc;
if(si->hasBranchTarget(pc, tc, bpc))
{
DPRINTF(Fail, "Immediate branch\n");
if (bpc.pc() != pc.npc())
{
m_BreakpointTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, bpc.pc());
}
}
}
void FailGem5Device::clearBreakpoints()
{
if(m_BreakpointTaken)
{
delete m_BreakpointTaken;
m_BreakpointTaken = 0;
}
if(m_BreakpointNotTaken)
{
delete m_BreakpointNotTaken;
m_BreakpointNotTaken = 0;
}
}
Tick FailGem5Device::read(PacketPtr pkt)
{
return pioDelay;

View File

@ -1,19 +0,0 @@
#ifndef __FAILGEM5_DEVICE_HH__
#define __FAILGEM5_DEVICE_HH__
#include "dev/io_device.hh"
#include "params/FailGem5Device.hh"
class FailGem5Device : public BasicPioDevice
{
public:
typedef FailGem5DeviceParams Params;
FailGem5Device(Params *p);
virtual Tick read(PacketPtr pkt);
virtual Tick write(PacketPtr pkt);
};
#endif // __FAILGEM5_DEVICE_HH__

View File

@ -0,0 +1,32 @@
#ifndef __FAILGEM5_DEVICE_HH__
#define __FAILGEM5_DEVICE_HH__
#include "dev/io_device.hh"
#include "params/FailGem5Device.hh"
#include "cpu/thread_context.hh"
class Gem5InstructionEvent;
class FailGem5Device : public BasicPioDevice
{
public:
typedef FailGem5DeviceParams Params;
FailGem5Device(Params *p);
void setNextBreakpoints(ThreadContext *tc);
virtual void startup();
virtual Tick read(PacketPtr pkt);
virtual Tick write(PacketPtr pkt);
private:
Gem5InstructionEvent* m_BreakpointTaken;
Gem5InstructionEvent* m_BreakpointNotTaken;
void activateSingleStepMode();
void deactivateSingleStepMode();
void clearBreakpoints();
};
#endif // __FAILGEM5_DEVICE_HH__

View File

@ -6,7 +6,7 @@
#if defined(BUILD_GEM5) && defined(CONFIG_EVENT_BREAKPOINTS)
#include "Gem5PCEvent.hh"
#include "Gem5PCEvents.hpp"
#include "sim/system.hh"
aspect Gem5Listener
@ -14,12 +14,12 @@ aspect Gem5Listener
advice "fail::BPSingleListener" : slice class
{
private:
Gem5PCEvent* m_Breakpoint;
Gem5BreakpointEvent* m_Breakpoint;
public:
virtual bool onAddition()
{
System* sys = *System::systemList.begin();
m_Breakpoint = new Gem5PCEvent(&sys->pcEventQueue, this->m_WatchInstrPtr);
m_Breakpoint = new Gem5BreakpointEvent(&sys->pcEventQueue, this->m_WatchInstrPtr);
return true;
}

View File

@ -1,7 +0,0 @@
#include "Gem5PCEvent.hh"
#include "../SALInst.hpp"
void Gem5PCEvent::process(ThreadContext *tc)
{
fail::simulator.onBreakpoint(this->evpc, fail::ANY_ADDR);
}

View File

@ -1,14 +0,0 @@
#ifndef __GEM5_PCEVENT_HPP__
#define __GEM5_PCEVENT_HPP__
#include "cpu/pc_event.hh"
class Gem5PCEvent : public PCEvent
{
public:
Gem5PCEvent(PCEventQueue* queue, Addr ip)
: PCEvent(queue, "Fail Breakpoint", ip) {}
virtual void process(ThreadContext *tc);
};
#endif // __GEM5_PCEVENT_HPP__

View File

@ -0,0 +1,14 @@
#include "Gem5PCEvents.hpp"
#include "../SALInst.hpp"
#include "cpu/thread_context.hh"
void Gem5BreakpointEvent::process(ThreadContext *tc)
{
fail::simulator.onBreakpoint(this->evpc, fail::ANY_ADDR);
}
void Gem5InstructionEvent::process(ThreadContext *tc)
{
m_FailDevice->setNextBreakpoints(tc);
}

View File

@ -0,0 +1,27 @@
#ifndef __GEM5_PCEVENTS_HPP__
#define __GEM5_PCEVENTS_HPP__
#include "cpu/pc_event.hh"
#include "FailGem5Device.hpp"
class Gem5BreakpointEvent : public PCEvent
{
public:
Gem5BreakpointEvent(PCEventQueue* queue, Addr ip)
: PCEvent(queue, "Fail breakpoint event", ip) {}
virtual void process(ThreadContext *tc);
};
class Gem5InstructionEvent : public PCEvent
{
public:
Gem5InstructionEvent(FailGem5Device* device, PCEventQueue* queue, Addr ip)
: PCEvent(queue, "Fail instruction event", ip), m_FailDevice(device) {}
virtual void process(ThreadContext *tc);
private:
FailGem5Device* m_FailDevice;
};
#endif // __GEM5_PCEVENTS_HPP__