Files
fail/src/core/sal/bochs/BochsController.cc
adrian 5c4b132550 ~SimulatorController: do not free ConcreteCPU object ptr in the base class
In fact, delete should be called in the destructor of each derived class (BochsController and Gem5Controller at the moment).

Additionally, this is the reason why ~SimulatorController is declared as virtual.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@2064 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
2013-02-06 15:39:50 +00:00

177 lines
4.6 KiB
C++

#include <sstream>
#include "BochsController.hpp"
#include "BochsMemory.hpp"
#include "../SALInst.hpp"
#include "../Listener.hpp"
namespace fail {
#ifdef DANCEOS_RESTORE
bx_bool restore_bochs_request = false;
bx_bool save_bochs_request = false;
std::string sr_path = "";
#endif
bx_bool reboot_bochs_request = false;
bx_bool interrupt_injection_request = false;
BochsController::BochsController()
: SimulatorController(new BochsMemoryManager()),
m_CPUContext(NULL), m_CurrentInstruction(NULL)
{
for (unsigned i = 0; i < BX_SMP_PROCESSORS; i++)
addCPU(new ConcreteCPU(i));
}
BochsController::~BochsController()
{
delete m_Mem;
std::vector<ConcreteCPU*>::iterator it = m_CPUs.begin();
while (it != m_CPUs.end()) {
delete *it;
it = m_CPUs.erase(it);
}
}
void BochsController::updateBPEventInfo(BX_CPU_C *context, bxInstruction_c *instr)
{
assert(context != NULL && "FATAL ERROR: Bochs internal member was NULL (not expected)!");
assert(instr != NULL && "FATAL ERROR: Bochs internal member was NULL (not expected)!");
m_CPUContext = context;
m_CurrentInstruction = instr;
}
void BochsController::onTimerTrigger(void* thisPtr)
{
// FIXME: The timer logic can be modified to use only one timer in Bochs.
// (For now, this suffices.)
TimerListener* pli = static_cast<TimerListener*>(thisPtr);
// Check for a matching TimerListener. (In fact, we are only
// interessted in the iterator pointing at pli.)
ListenerManager::iterator it = std::find(simulator.m_LstList.begin(),
simulator.m_LstList.end(), pli);
// TODO: This has O(|m_LstList|) time complexity. We can further improve this
// by creating a method such that makeActive(pli) works as well,
// reducing the time complexity to O(1).
simulator.m_LstList.makeActive(it);
simulator.m_LstList.triggerActiveListeners();
}
void BochsController::onIOPort(ConcreteCPU* cpu, unsigned char data, unsigned port, bool out) {
// Check for active IOPortListeners:
ListenerManager::iterator it = m_LstList.begin();
while (it != m_LstList.end()) {
BaseListener* pLi = *it;
IOPortListener* pIOPt = dynamic_cast<IOPortListener*>(pLi);
if (pIOPt != NULL && pIOPt->isMatching(port, out)) {
pIOPt->setData(data);
pIOPt->setTriggerCPU(cpu);
it = m_LstList.makeActive(it);
// "it" has already been set to the next element (by calling
// makeActive()):
continue; // -> skip iterator increment
}
it++;
}
m_LstList.triggerActiveListeners();
}
bool BochsController::save(const std::string& path)
{
int stat;
stat = mkdir(path.c_str(), 0777);
if (!(stat == 0 || errno == EEXIST)) {
return false;
// std::cout << "[FAIL] Can not create target-directory to save!" << std::endl;
// TODO: (Non-)Verbose-Mode? Log-level? Maybe better: use return value to indicate failure?
}
save_bochs_request = true;
BX_CPU(0)->async_event |= 1;
sr_path = path;
m_CurrFlow = m_Flows.getCurrent();
m_Flows.resume();
return true;
}
void BochsController::saveDone()
{
save_bochs_request = false;
m_Flows.toggle(m_CurrFlow);
}
void BochsController::restore(const std::string& path)
{
clearListeners();
restore_bochs_request = true;
BX_CPU(0)->async_event |= 1;
sr_path = path;
m_CurrFlow = m_Flows.getCurrent();
m_Flows.resume();
}
void BochsController::restoreDone()
{
restore_bochs_request = false;
m_Flows.toggle(m_CurrFlow);
}
void BochsController::reboot()
{
clearListeners();
reboot_bochs_request = true;
BX_CPU(0)->async_event |= 1;
m_CurrFlow = m_Flows.getCurrent();
m_Flows.resume();
}
void BochsController::rebootDone()
{
reboot_bochs_request = false;
m_Flows.toggle(m_CurrFlow);
}
void BochsController::fireInterrupt(unsigned irq)
{
interrupt_injection_request = true;
interrupt_to_fire = irq;
// FIXME needed? BX_CPU(0)->async_event |= 1;
m_CurrFlow = m_Flows.getCurrent();
m_Flows.resume();
}
void BochsController::fireInterruptDone()
{
interrupt_injection_request = false;
m_Flows.toggle(m_CurrFlow);
}
const std::string& BochsController::getMnemonic() const
{
static std::string str;
bxInstruction_c* pInstr = getCurrentInstruction();
assert(pInstr != NULL && "FATAL ERROR: Bochs internal member was NULL (not expected)!");
const char* pszName = get_bx_opcode_name(pInstr->getIaOpcode());
if (pszName != NULL)
str = pszName;
else
str.clear();
return str;
}
ConcreteCPU& BochsController::detectCPU(BX_CPU_C* pCPU) const
{
unsigned i = 0;
#if BX_SUPPORT_SMP
for (; i < BX_SMP_PROCESSORS; i++) {
if (BX_CPU_C[i] == pCPU) // cmp this ptr with all possible CPU objects
break; // index "i" found! -> stop!
}
#endif
return getCPU(i);
}
} // end-of-namespace: fail