Merge branch 'save-restore-behavior'

This commit is contained in:
Horst Schirmeier
2015-04-08 17:45:40 +02:00
12 changed files with 74 additions and 48 deletions

View File

@ -109,28 +109,29 @@ bool DatabaseExperiment::run()
simulator.clearListeners(); simulator.clearListeners();
// Generate an experiment listener, that matches on any IP
// event. It is used to forward to the injection
// point. The +1 is needed, since even for the zeroth
// dynamic instruction we need at least one breakpoint
// event.
BPSingleListener bp;
bp.setWatchInstructionPointer(ANY_ADDR);
bp.setCounter(injection_instr + 1);
simulator.addListener(&bp);
if (!this->cb_before_fast_forward()) { if (!this->cb_before_fast_forward()) {
continue; continue;
} }
fail::BaseListener * listener;
while (true) { // Do we need to fast-forward at all?
listener = simulator.resume(); if (injection_instr > 0) {
if (listener == &bp) { // Create a listener that matches any IP event. It is used to
break; // forward to the injection point.
} else { BPSingleListener bp;
bool should_continue = this->cb_during_fast_forward(listener); bp.setWatchInstructionPointer(ANY_ADDR);
if (!should_continue) bp.setCounter(injection_instr);
break; // Stop fast forwarding simulator.addListener(&bp);
fail::BaseListener * listener;
while (true) {
listener = simulator.resume();
if (listener == &bp) {
break;
} else {
bool should_continue = this->cb_during_fast_forward(listener);
if (!should_continue)
break; // Stop fast forwarding
}
} }
} }
if (!this->cb_after_fast_forward(listener)) { if (!this->cb_after_fast_forward(listener)) {

View File

@ -9,6 +9,7 @@ namespace fail {
#ifdef DANCEOS_RESTORE #ifdef DANCEOS_RESTORE
bx_bool restore_bochs_request = false; bx_bool restore_bochs_request = false;
bx_bool restore_bochs_finished = false;
bx_bool save_bochs_request = false; bx_bool save_bochs_request = false;
std::string sr_path = ""; std::string sr_path = "";
#endif #endif
@ -106,6 +107,7 @@ void BochsController::restore(const std::string& path)
{ {
clearListeners(); clearListeners();
restore_bochs_request = true; restore_bochs_request = true;
restore_bochs_finished = false;
BX_CPU(0)->async_event |= 1; BX_CPU(0)->async_event |= 1;
sr_path = path; sr_path = path;
m_CurrFlow = m_Flows.getCurrent(); m_CurrFlow = m_Flows.getCurrent();
@ -114,7 +116,6 @@ void BochsController::restore(const std::string& path)
void BochsController::restoreDone() void BochsController::restoreDone()
{ {
restore_bochs_request = false;
m_Flows.toggle(m_CurrFlow); m_Flows.toggle(m_CurrFlow);
} }

View File

@ -9,6 +9,7 @@ namespace fail {
#ifdef DANCEOS_RESTORE #ifdef DANCEOS_RESTORE
extern bx_bool restore_bochs_request; extern bx_bool restore_bochs_request;
extern bx_bool restore_bochs_finished;
extern bx_bool save_bochs_request; extern bx_bool save_bochs_request;
extern std::string sr_path; extern std::string sr_path;
#endif #endif

View File

@ -13,10 +13,30 @@
#include "../SALInst.hpp" #include "../SALInst.hpp"
aspect RestoreState { aspect RestoreState {
pointcut restoreState() = "void bx_sr_after_restore_state()"; pointcut restoreState() = "void bx_sr_after_restore_state()";
pointcut cpuLoop() = "void defineCPULoopJoinPoint(...)";
advice execution (restoreState()) : after () advice execution (restoreState()) : after ()
{ {
// did the experiment trigger this restore?
if (fail::restore_bochs_request) {
fail::restore_bochs_request = false;
fail::restore_bochs_finished = true;
}
}
// Make sure the "RestoreState" aspect comes *after* the breakpoint stuff
// to create a simulator / experiment state very similar to when the state
// was saved. In an "after" advice this means it must get a *higher*
// precedence, therefore it's first in the order list.
advice execution (cpuLoop()) : order ("RestoreState", "Breakpoints");
advice execution (cpuLoop()) : after ()
{
if (!fail::restore_bochs_finished) {
return;
}
fail::restore_bochs_finished = false;
std::cout << "[FAIL] Restore finished" << std::endl; std::cout << "[FAIL] Restore finished" << std::endl;
// TODO: Log-Level? // TODO: Log-Level?
fail::simulator.restoreDone(); fail::simulator.restoreDone();

View File

@ -19,13 +19,14 @@ aspect SaveState {
advice execution (cpuLoop()) : order ("SaveState", "Breakpoints"); advice execution (cpuLoop()) : order ("SaveState", "Breakpoints");
advice execution (cpuLoop()) : after () { advice execution (cpuLoop()) : after () {
if (!fail::save_bochs_request) // loop allows to call save() multiple times in a row
return; while (fail::save_bochs_request) {
assert(fail::sr_path.size() > 0 && "FATAL ERROR: tried to save state without valid path"); assert(fail::sr_path.size() > 0 && "FATAL ERROR: tried to save state without valid path");
SIM->save_state(fail::sr_path.c_str()); SIM->save_state(fail::sr_path.c_str());
std::cout << "[FAIL] Save finished" << std::endl; std::cout << "[FAIL] Save finished" << std::endl;
// TODO: Log-Level? // TODO: Log-Level?
fail::simulator.saveDone(); fail::simulator.saveDone();
}
} }
}; };

View File

@ -321,18 +321,22 @@ bool CoredTester::run() {
simulator.addListener(&l_fail_trace); simulator.addListener(&l_fail_trace);
BPSingleListener bp; BPSingleListener bp;
bp.setWatchInstructionPointer(ANY_ADDR); fail::BaseListener *listener = 0;
// TODO: why does this need a +1?
bp.setCounter(injection_instr+1);
simulator.addListener(&bp);
fail::BaseListener * listener = simulator.resume();
bool ok = true; bool ok = true;
while ( ok && (listener == &l_fail_trace) ) { // do we have to fast-forward at all?
// m_log << "CP IP 0x" << std::hex << simulator.getCPU(0).getInstructionPointer() << std::endl; if (injection_instr > 0) {
ok = cpoint.check(s_fail_trace, l_fail_trace.getTriggerInstructionPointer()) == Checkpoint::IDENTICAL; bp.setWatchInstructionPointer(ANY_ADDR);
if(ok) listener = simulator.addListenerAndResume(&l_fail_trace); bp.setCounter(injection_instr);
simulator.addListener(&bp);
listener = simulator.resume();
while ( ok && (listener == &l_fail_trace) ) {
// m_log << "CP IP 0x" << std::hex << simulator.getCPU(0).getInstructionPointer() << std::endl;
ok = cpoint.check(s_fail_trace, l_fail_trace.getTriggerInstructionPointer()) == Checkpoint::IDENTICAL;
if(ok) listener = simulator.addListenerAndResume(&l_fail_trace);
}
} }
unsigned experiment_number = cpoint.getCount(); unsigned experiment_number = cpoint.getCount();
@ -347,7 +351,7 @@ bool CoredTester::run() {
break; break;
} }
if (listener != &bp) { if (listener != &bp && injection_instr > 0) {
result = param.msg.add_result(); result = param.msg.add_result();
handleEvent(*result, result->NOINJECTION, "WTF"); handleEvent(*result, result->NOINJECTION, "WTF");

View File

@ -349,11 +349,11 @@ bool CoredVoter::run() {
// Fast forward to injection address // Fast forward to injection address
m_log << "Trying to inject @ instr #" << dec << injection_instr << endl; m_log << "Trying to inject @ instr #" << dec << injection_instr << endl;
if ((injection_instr + 2) > 0) { if (injection_instr > 0) {
simulator.clearListeners(); simulator.clearListeners();
BPSingleListener bp; BPSingleListener bp;
bp.setWatchInstructionPointer(ANY_ADDR); bp.setWatchInstructionPointer(ANY_ADDR);
bp.setCounter(injection_instr + 2); // FIXME: FISHY! bp.setCounter(injection_instr);
simulator.addListener(&bp); simulator.addListener(&bp);
fail::BaseListener * listener = simulator.resume(); fail::BaseListener * listener = simulator.resume();

View File

@ -197,7 +197,7 @@ bool DCIAOKernelStructs::run() {
simulator.addListener(&l_time_marker_print); simulator.addListener(&l_time_marker_print);
bp.setWatchInstructionPointer(ANY_ADDR); bp.setWatchInstructionPointer(ANY_ADDR);
bp.setCounter(injection_instr+1); bp.setCounter(injection_instr);
simulator.addListener(&bp); simulator.addListener(&bp);
// Add vport listener // Add vport listener

View File

@ -253,7 +253,7 @@ bool FiascoFailExperiment::faultInjection()
if(instr_offset > 0) if(instr_offset > 0)
{ {
bp.setWatchInstructionPointer(ANY_ADDR); // Create new Breakpoint... bp.setWatchInstructionPointer(ANY_ADDR); // Create new Breakpoint...
bp.setCounter(instr_offset + 1); // ...to break when the IP for the fault injection is reached... bp.setCounter(instr_offset); // ...to break when the IP for the fault injection is reached...
simulator.addListener(&bp); // ...and add it to the actual listeners simulator.addListener(&bp); // ...and add it to the actual listeners
BaseListener *go = waitIOOrOther(true); // Resume simulation and log VGA-Output BaseListener *go = waitIOOrOther(true); // Resume simulation and log VGA-Output

View File

@ -187,8 +187,7 @@ bool KESOgc::run()
BPSingleListener bp; BPSingleListener bp;
bp.setWatchInstructionPointer(ANY_ADDR); bp.setWatchInstructionPointer(ANY_ADDR);
// Fix offset by 1 error bp.setCounter(injection_instr);
bp.setCounter(injection_instr + 1);
simulator.addListener(&bp); simulator.addListener(&bp);

View File

@ -161,7 +161,7 @@ bool KESOrefs::run()
BPSingleListener bp; BPSingleListener bp;
bp.setWatchInstructionPointer(ANY_ADDR); bp.setWatchInstructionPointer(ANY_ADDR);
bp.setCounter(injection_instr + 1); bp.setCounter(injection_instr);
simulator.addListener(&bp); simulator.addListener(&bp);
bool inject = true; bool inject = true;

View File

@ -160,8 +160,7 @@ bool VEZSExperiment::run()
BPSingleListener bp; BPSingleListener bp;
bp.setWatchInstructionPointer(ANY_ADDR); bp.setWatchInstructionPointer(ANY_ADDR);
// Fix offset by 1 error bp.setCounter(injection_instr);
bp.setCounter(injection_instr + 1);
simulator.addListener(&bp); simulator.addListener(&bp);