Files
fail/src/core/sal/bochs/BochsController.cc
adrian f8aa1237e9 Make FailBochs compile again (after changes in r1966).
For now, only breakpoints are working. Other event sources need to be revised, too.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1981 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
2012-12-12 13:08:43 +00:00

161 lines
4.2 KiB
C++

#include <sstream>
#include "BochsController.hpp"
#include "BochsMemory.hpp"
//#include "BochsRegister.hpp"
//#include "../Register.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;
}
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(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);
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;
}
} // end-of-namespace: fail