Files
fail/src/core/sal/bochs/BochsController.cc
Horst Schirmeier a7184af37b core/sal: uninitialized BochsController member
False positive, nevertheless worth fixing.  Found by Coverity Scan,
CID 25723.

Change-Id: Ia4f1eb033d7cc8c20889280a59d8973ecf768933
2015-02-07 17:29:34 +01: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_CurrFlow(NULL), 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