Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/core/comm/TracePlugin.proto
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ message Trace_Event {
// and for target backends capable of timing-accurate execution
optional int64 time_delta = 6;
optional uint64 memaddr = 2;
optional uint32 memtype = 7;
optional uint32 width = 3;
enum AccessType {
READ = 1;
Expand Down
37 changes: 32 additions & 5 deletions src/core/sal/Event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace fail {

/**
* \class BaseEvent
* This is the base class for all event types. It encapsulates the information
* This is the base class for all event types. It encapsulates the information
* about an event reported by the simulator backend.
*/
class BaseEvent {
Expand Down Expand Up @@ -99,15 +99,20 @@ class MemAccessEvent : public BaseEvent {
address_t m_TriggerIP;
//! Memory access type at m_TriggerAddr.
access_type_t m_AccessType;
//! Specific memory type in which this access occured.
memory_type_t m_MemType;
//! The data that was accessed in this event.
uint64_t m_Data;
public:
/**
* Creates a new \c MemAccessEvent using default initialization values, i.e.
* \c setTriggerAddress(ANY_ADDR), \c setTriggerWidth(0), \c setTriggerAccessType(MEM_UNKNOWN),
* \c setTriggerInstructionPointer(ANY_ADDR) and setTriggerCPU(NULL).
* \c setTriggerInstructionPointer(ANY_ADDR), setMemType(MEMTYPE_RAM), and setTriggerCPU(NULL).
*/
MemAccessEvent()
: m_TriggerAddr(ANY_ADDR), m_TriggerWidth(0),
m_TriggerIP(ANY_ADDR), m_AccessType(MEM_UNKNOWN) { }
m_TriggerIP(ANY_ADDR), m_AccessType(MEM_UNKNOWN),
m_MemType(MEMTYPE_RAM), m_Data(0){ }
/**
* Creates a new \c MemAccessEvent and initializes the provided values.
* @param triggerAddr actual address that triggered the event
Expand All @@ -117,9 +122,9 @@ class MemAccessEvent : public BaseEvent {
* @param cpu the CPU that triggered the event
*/
MemAccessEvent(address_t triggerAddr, size_t width, address_t triggerIP, access_type_t type,
ConcreteCPU* cpu = NULL)
ConcreteCPU* cpu = NULL, memory_type_t memtype=MEMTYPE_RAM, uint64_t data=0)
: BaseEvent(cpu), m_TriggerAddr(triggerAddr), m_TriggerWidth(width),
m_TriggerIP(triggerIP), m_AccessType(type) { }
m_TriggerIP(triggerIP), m_AccessType(type), m_MemType(memtype), m_Data(data){ }
/**
* Returns the specific memory address that actually triggered the event.
* @return the triggering address
Expand All @@ -131,6 +136,28 @@ class MemAccessEvent : public BaseEvent {
* @param addr the new triggering address
*/
void setTriggerAddress(address_t addr) { m_TriggerAddr = addr; }
/**
* Returns the type of memory which actually triggered the event.
* @return A memory_type_t which corresponds to the memory which triggered the event.
*/
memory_type_t getMemoryType() const { return m_MemType; }
/**
* Set the specific memory type which triggered the event.
* Should not be used by experiment code.
* @param type the new memory type.
*/
void setMemoryType(memory_type_t type) { m_MemType = type; }
/**
* Returns the data at the memory location that was accessed if it is available.
* @return The value of the accessed memory location .
*/
uint64_t getAccessedData() const { return m_Data; }
/**
* Set the data, which was accessed during the memory event.
* Should not be used by experiment code.
* @param data The data to be saved.
*/
void setAccessedData(uint64_t data) { m_Data = data; }
/**
* Returns the specific number of bytes read or written at \c getTriggerAddress().
* @return the width of the memory access
Expand Down
6 changes: 4 additions & 2 deletions src/core/sal/Listener.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ bool MemAccessListener::isMatching(const MemAccessEvent* pEv) const
if (!(m_WatchType & pEv->getTriggerAccessType())) {
return false;
} else if (m_WatchAddr != ANY_ADDR
&& (m_WatchAddr >= pEv->getTriggerAddress() + pEv->getTriggerWidth()
|| m_WatchAddr + m_WatchWidth <= pEv->getTriggerAddress())) {
&& (m_WatchAddr >= pEv->getTriggerAddress() + pEv->getTriggerWidth()
|| m_WatchAddr + m_WatchWidth <= pEv->getTriggerAddress())) {
return false;
} else if (m_WatchMemType != ANY_MEMORY && m_WatchMemType != pEv->getMemoryType()) {
return false;
} else if (m_CPU != NULL && m_CPU != pEv->getTriggerCPU()) {
return false;
Expand Down
59 changes: 48 additions & 11 deletions src/core/sal/Listener.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ class MemAccessListener : public BaseListener {
protected:
//! Specific physical guest system address to watch, or ANY_ADDR.
address_t m_WatchAddr;
//! Specific memory type to watch (e.g. Tag memory), or ANY_MEMORY.
memory_type_t m_WatchMemType;
//! Width of the memory area being watched (# bytes).
size_t m_WatchWidth;
/**
Expand All @@ -326,15 +328,15 @@ class MemAccessListener : public BaseListener {
WP_CTOR_SCOPE:
MemAccessListener(MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
ConcreteCPU* cpu = NULL)
: BaseListener(cpu), m_WatchAddr(ANY_ADDR), m_WatchWidth(1), m_WatchType(type) { }
MemAccessListener(address_t addr,
MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
: BaseListener(cpu), m_WatchAddr(ANY_ADDR), m_WatchMemType(ANY_MEMORY), m_WatchWidth(1), m_WatchType(type), m_Data() { }
MemAccessListener(address_t addr, memory_type_t memtype = ANY_MEMORY,
MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
ConcreteCPU* cpu = NULL)
: BaseListener(cpu), m_WatchAddr(addr), m_WatchWidth(1), m_WatchType(type) { }
MemAccessListener(const ElfSymbol &symbol,
MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
: BaseListener(cpu), m_WatchAddr(addr), m_WatchMemType(memtype), m_WatchWidth(1), m_WatchType(type), m_Data() { }
MemAccessListener(const ElfSymbol &symbol, memory_type_t memtype = ANY_MEMORY,
MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
ConcreteCPU* cpu = NULL)
: BaseListener(cpu), m_WatchAddr(symbol.getAddress()), m_WatchWidth(symbol.getSize()), m_WatchType(type) { }
: BaseListener(cpu), m_WatchAddr(symbol.getAddress()), m_WatchMemType(memtype), m_WatchWidth(symbol.getSize()), m_WatchType(type) , m_Data() { }
public:
/**
* Returns the physical memory address to be observed.
Expand All @@ -344,6 +346,14 @@ class MemAccessListener : public BaseListener {
* Sets the physical memory address to be observed. (Wildcard: ANY_ADDR)
*/
void setWatchAddress(address_t addr) { m_WatchAddr = addr; }
/**
* Returns the memory type to be observed.
*/
memory_type_t getWatchMemoryType() const { return m_WatchMemType; }
/**
* Sets the memory type to be observed. (Wildcard: ANY_MEMORY)
*/
void setWatchMemoryType(memory_type_t type) { m_WatchMemType = type; }
/**
* Returns the width of the memory area being watched.
*/
Expand All @@ -370,6 +380,33 @@ class MemAccessListener : public BaseListener {
* listener. Should not be used by experiment code.
*/
void setTriggerAddress(address_t addr) { m_Data.setTriggerAddress(addr); }
/**
* Returns the type of memory which actually triggered the event.
* @return A memory_type_t which corresponds to the memory which triggered the event.
*/
memory_type_t getTriggerMemoryType() const { return m_Data.getMemoryType(); }
/**
* Set the specific memory type which triggered the event.
* Should not be used by experiment code.
* @param type the new memory type.
*/
void setTriggerMemoryType(memory_type_t type) { m_Data.setMemoryType(type); }
/**
* Returns the data at the memory location that was accessed if it is available.
* @return A uint64_t which contains at most 8 bytes of the accessed data.
*/
uint64_t getAccessedData() const { return m_Data.getAccessedData(); }
/**
* Set the data, which was accessed during the memory event.
* This data is copied into this class.
* Should not be used by experiment code.
* @param type the new memory type.
*/
void setAccessedData(uint64_t data) { m_Data.setAccessedData(data); }
/**
* Returns the specific number of bytes read or written at \c getTriggerAddress().
* @return the width of the memory access
*/
/**
* Returns the width (in bytes) of the memory access that triggered this
* listener.
Expand Down Expand Up @@ -425,8 +462,8 @@ class MemReadListener : public MemAccessListener {
WPREAD_CTOR_SCOPE:
MemReadListener(ConcreteCPU* cpu = NULL)
: MemAccessListener(MemAccessEvent::MEM_READ, cpu) { }
MemReadListener(address_t addr, ConcreteCPU* cpu = NULL)
: MemAccessListener(addr, MemAccessEvent::MEM_READ, cpu) { }
MemReadListener(address_t addr, memory_type_t type = ANY_MEMORY, ConcreteCPU* cpu = NULL)
: MemAccessListener(addr, type, MemAccessEvent::MEM_READ, cpu) { }
};

#ifdef CONFIG_EVENT_MEMWRITE
Expand All @@ -442,8 +479,8 @@ class MemWriteListener : public MemAccessListener {
WPWRITE_CTOR_SCOPE:
MemWriteListener(ConcreteCPU* cpu = NULL)
: MemAccessListener(MemAccessEvent::MEM_WRITE, cpu) { }
MemWriteListener(address_t addr, ConcreteCPU* cpu = NULL)
: MemAccessListener(addr, MemAccessEvent::MEM_WRITE, cpu) { }
MemWriteListener(address_t addr, memory_type_t type = ANY_MEMORY, ConcreteCPU* cpu = NULL)
: MemAccessListener(addr, type, MemAccessEvent::MEM_WRITE, cpu) { }
};

#if defined CONFIG_EVENT_INTERRUPT || defined CONFIG_EVENT_TRAP
Expand Down
1 change: 1 addition & 0 deletions src/core/sal/SALConfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace fail {
defined BUILD_PANDA
const address_t ADDR_INV = static_cast<address_t> (0);
const address_t ANY_ADDR = static_cast<address_t> (-1);
const memory_type_t ANY_MEMORY = static_cast<memory_type_t> (-1);
const unsigned ANY_INSTR = static_cast<unsigned> (-1);
const unsigned ANY_TRAP = static_cast<unsigned> (-1);
const unsigned ANY_INTERRUPT = static_cast<unsigned> (-1);
Expand Down
10 changes: 10 additions & 0 deletions src/core/sal/SALConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,22 @@ typedef uint64_t simtime_t;
//! backend-specific notion of time difference
typedef int64_t simtime_diff_t;

typedef enum {
MEMTYPE_UNKNOWN = 0x0, //!< Somehow, we do not know
MEMTYPE_RAM = 0x1, //!< Access to volatile memory
MEMTYPE_FLASH = 0x2, //!< Access to flash memory
MEMTYPE_TAGS = 0x3, //!< Access to tag-bits (see SAIL)
MEMTYPE_EEPROM = 0x4 //!< Access to EEPROM (see AVR)
} memory_type_t; //! memory type (RAM, FLASH, etc...)

// Note: The following flags are defined in SALConfig.cc.

//! invalid address flag (e.g. for memory address ptrs)
extern const address_t ADDR_INV;
//! address wildcard (e.g. for breakpoint listeners)
extern const address_t ANY_ADDR;
//! memory type wildcard (e.g. for memory access listener)
extern const memory_type_t ANY_MEMORY;
//! instruction wildcard (e.g. for jump listeners)
extern const unsigned ANY_INSTR;
//! trap wildcard
Expand Down
22 changes: 18 additions & 4 deletions src/core/sal/SimulatorController.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Event.hpp"
#include "Listener.hpp"
#include "util/CommandLine.hpp"
#include "Memory.hpp"

namespace fail {

Expand Down Expand Up @@ -136,15 +137,16 @@ void SimulatorController::onBreakpoint(ConcreteCPU* cpu, address_t instrPtr, add
m_LstList.triggerActiveListeners();
}

void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len,
bool is_write, address_t instrPtr)
void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len,
bool is_write, address_t instrPtr, memory_type_t type)
{
MemAccessEvent::access_type_t accesstype =
is_write ? MemAccessEvent::MEM_WRITE
: MemAccessEvent::MEM_READ;

MemAccessEvent tmp(addr, len, instrPtr, accesstype, cpu);
MemAccessEvent tmp(addr, len, instrPtr, accesstype, cpu, type);
ListenerManager::iterator it = m_LstList.begin();

while (it != m_LstList.end()) { // check for active listeners
BaseListener* pev = *it;
MemAccessListener* ev = dynamic_cast<MemAccessListener*>(pev);
Expand All @@ -159,6 +161,18 @@ void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_
ev->setTriggerAccessType(accesstype);
ev->setTriggerCPU(cpu);
it = m_LstList.makeActive(it);

// Read Memory with help of Memory Manager
ev->setTriggerMemoryType(type);
if (type == MEMTYPE_RAM) {
uint64_t data = 0;
MemoryManager &mm = getMemoryManager(type);
char max_len = len > sizeof(data) ? sizeof(data) : len;
if (mm.isMapped(addr) && mm.isMapped(addr + len - 1)) {
mm.getBytes(addr, max_len, &data);
ev->setAccessedData(data);
}
}
}
m_LstList.triggerActiveListeners();
}
Expand Down Expand Up @@ -276,7 +290,7 @@ BaseListener* SimulatorController::addListenerAndResume(BaseListener* li)
void SimulatorController::terminate(int exCode)
{
// Attention: This could cause problems, e.g., because of non-closed sockets
std::cout << "[FAIL] Exit called by experiment with exit code: " << exCode << std::endl;
m_log << "[FAIL] Exit called by experiment with exit code: " << exCode << std::endl;
// TODO: (Non-)Verbose-Mode? Log-Level?

m_Flows.setTerminated(); // we are about to terminate
Expand Down
28 changes: 18 additions & 10 deletions src/core/sal/SimulatorController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,20 @@ class SimulatorController {
ListenerManager m_LstList; //!< storage where listeners are being buffered
std::map<std::string, ExperimentFlow *> m_Experiments; //!< registered experiments, one is chosen on startup
CoroutineManager m_Flows; //!< managed experiment flows
MemoryManager *m_Mem; //!< access to memory pool
std::map<memory_type_t, MemoryManager *> m_Mems; //!< access to memory pool(s)
std::vector<ConcreteCPU*> m_CPUs; //!< list of CPUs in the target system
friend class ListenerManager; //!< "outsources" the listener management
std::string m_argv0; //!< Invocation name of simulator process
public:
SimulatorController()
: m_log("SimulatorController", false),
m_isInitialized(false),
m_Mem(nullptr)
m_isInitialized(false)
{ /* blank */ }
SimulatorController(MemoryManager* mem)
: m_log("SimulatorController", false),
m_isInitialized(false),
m_Mem(mem)
{ /* blank */ }
m_isInitialized(false) {
m_Mems[MEMTYPE_RAM] = mem; // The RAM memory manager is the default
}
virtual ~SimulatorController() { }
/**
* @brief Initialization function each implementation needs to call on
Expand Down Expand Up @@ -95,11 +94,14 @@ class SimulatorController {
* @param len the length of the accessed memory
* @param is_write \c true if memory is written, \c false if read
* @param instrPtr the address of the instruction causing the memory
* @param type The type of memory that was accessed.
* @param data The data which is stored at the memory location which was accessed. At most 8 bytes are supported, passed in the form of a concatenated 64 bit integer.
* access
*
* FIXME: should instrPtr be part of this interface?
*/
void onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, bool is_write, address_t instrPtr);
void onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, bool is_write, address_t instrPtr,
memory_type_t type=MEMTYPE_RAM);
/**
* Interrupt handler.
* @param cpu the CPU that caused the interrupt
Expand Down Expand Up @@ -174,13 +176,19 @@ class SimulatorController {
* Returns the (constant) initialized memory manager.
* @return a reference to the memory manager
*/
MemoryManager& getMemoryManager() { return *m_Mem; }
const MemoryManager& getMemoryManager() const { return *m_Mem; }
MemoryManager& getMemoryManager(memory_type_t type=MEMTYPE_RAM) {
return *m_Mems.at(type);
}
const MemoryManager& getMemoryManager(memory_type_t type=MEMTYPE_RAM) const {
return *m_Mems.at(type);
}
/**
* Sets the memory manager.
* @param pMem a new concrete memory manager
*/
void setMemoryManager(MemoryManager* pMem) { m_Mem = pMem; }
void setMemoryManager(MemoryManager* pMem, memory_type_t type=MEMTYPE_RAM) {
m_Mems[type] = pMem;
}
/* ********************************************************************
* Experiment-Flow & Listener Management API:
* ********************************************************************/
Expand Down
2 changes: 1 addition & 1 deletion src/core/sal/bochs/BochsController.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ BochsController::BochsController()

BochsController::~BochsController()
{
delete m_Mem;
delete &getMemoryManager();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point only the MemoryManager for MEMTYPE_RAM would be deleted, since this is the default for getMemoryManager().

std::vector<ConcreteCPU*>::iterator it = m_CPUs.begin();
while (it != m_CPUs.end()) {
delete *it;
Expand Down
2 changes: 1 addition & 1 deletion src/core/sal/gem5/Gem5Controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Gem5Controller::~Gem5Controller()
delete *it;
it = m_CPUs.erase(it);
}
delete m_Mem;
delete &getMemoryManager();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point only the MemoryManager for MEMTYPE_RAM would be deleted, since this is the default for getMemoryManager().

}

bool Gem5Controller::save(const std::string &path)
Expand Down
2 changes: 1 addition & 1 deletion src/core/sal/panda/PandaController.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ PandaController::PandaController()

PandaController::~PandaController()
{
delete m_Mem;
std::vector<ConcreteCPU*>::iterator it = m_CPUs.begin();
while (it != m_CPUs.end()) {
delete *it;
it = m_CPUs.erase(it);
}
delete &getMemoryManager();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point only the MemoryManager for MEMTYPE_RAM would be deleted, since this is the default for getMemoryManager().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine for Panda, since there is only one kind of memor manager.

}

void PandaController::onTimerTrigger(void* thisPtr)
Expand Down
Loading