diff --git a/src/core/efw/DatabaseExperiment.cc b/src/core/efw/DatabaseExperiment.cc index 82fccf24..93736d1d 100644 --- a/src/core/efw/DatabaseExperiment.cc +++ b/src/core/efw/DatabaseExperiment.cc @@ -109,28 +109,29 @@ bool DatabaseExperiment::run() 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()) { continue; } - 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 + + // Do we need to fast-forward at all? + if (injection_instr > 0) { + // Create a listener that matches any IP event. It is used to + // forward to the injection point. + BPSingleListener bp; + bp.setWatchInstructionPointer(ANY_ADDR); + bp.setCounter(injection_instr); + 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)) { diff --git a/src/core/sal/bochs/BochsController.cc b/src/core/sal/bochs/BochsController.cc index f527c1e1..7b8aa140 100644 --- a/src/core/sal/bochs/BochsController.cc +++ b/src/core/sal/bochs/BochsController.cc @@ -9,6 +9,7 @@ namespace fail { #ifdef DANCEOS_RESTORE bx_bool restore_bochs_request = false; +bx_bool restore_bochs_finished = false; bx_bool save_bochs_request = false; std::string sr_path = ""; #endif @@ -106,6 +107,7 @@ void BochsController::restore(const std::string& path) { clearListeners(); restore_bochs_request = true; + restore_bochs_finished = false; BX_CPU(0)->async_event |= 1; sr_path = path; m_CurrFlow = m_Flows.getCurrent(); @@ -114,7 +116,6 @@ void BochsController::restore(const std::string& path) void BochsController::restoreDone() { - restore_bochs_request = false; m_Flows.toggle(m_CurrFlow); } diff --git a/src/core/sal/bochs/FailBochsGlobals.hpp b/src/core/sal/bochs/FailBochsGlobals.hpp index 8ee30bbf..50346dea 100644 --- a/src/core/sal/bochs/FailBochsGlobals.hpp +++ b/src/core/sal/bochs/FailBochsGlobals.hpp @@ -9,6 +9,7 @@ namespace fail { #ifdef DANCEOS_RESTORE extern bx_bool restore_bochs_request; +extern bx_bool restore_bochs_finished; extern bx_bool save_bochs_request; extern std::string sr_path; #endif diff --git a/src/core/sal/bochs/RestoreState.ah b/src/core/sal/bochs/RestoreState.ah index 9c9001f6..9ad278c2 100644 --- a/src/core/sal/bochs/RestoreState.ah +++ b/src/core/sal/bochs/RestoreState.ah @@ -13,10 +13,30 @@ #include "../SALInst.hpp" 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 () { + // 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; // TODO: Log-Level? fail::simulator.restoreDone(); diff --git a/src/core/sal/bochs/SaveState.ah b/src/core/sal/bochs/SaveState.ah index f0f11699..9a479d58 100644 --- a/src/core/sal/bochs/SaveState.ah +++ b/src/core/sal/bochs/SaveState.ah @@ -19,13 +19,14 @@ aspect SaveState { advice execution (cpuLoop()) : order ("SaveState", "Breakpoints"); advice execution (cpuLoop()) : after () { - if (!fail::save_bochs_request) - return; - assert(fail::sr_path.size() > 0 && "FATAL ERROR: tried to save state without valid path"); - SIM->save_state(fail::sr_path.c_str()); - std::cout << "[FAIL] Save finished" << std::endl; - // TODO: Log-Level? - fail::simulator.saveDone(); + // loop allows to call save() multiple times in a row + while (fail::save_bochs_request) { + assert(fail::sr_path.size() > 0 && "FATAL ERROR: tried to save state without valid path"); + SIM->save_state(fail::sr_path.c_str()); + std::cout << "[FAIL] Save finished" << std::endl; + // TODO: Log-Level? + fail::simulator.saveDone(); + } } }; diff --git a/src/experiments/cored-tester/experiment.cc b/src/experiments/cored-tester/experiment.cc index 0e8a486d..a5cc698a 100644 --- a/src/experiments/cored-tester/experiment.cc +++ b/src/experiments/cored-tester/experiment.cc @@ -321,18 +321,22 @@ bool CoredTester::run() { simulator.addListener(&l_fail_trace); BPSingleListener bp; - bp.setWatchInstructionPointer(ANY_ADDR); - // TODO: why does this need a +1? - bp.setCounter(injection_instr+1); - simulator.addListener(&bp); - - fail::BaseListener * listener = simulator.resume(); + fail::BaseListener *listener = 0; bool ok = true; - 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); + // do we have to fast-forward at all? + if (injection_instr > 0) { + bp.setWatchInstructionPointer(ANY_ADDR); + 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(); @@ -347,7 +351,7 @@ bool CoredTester::run() { break; } - if (listener != &bp) { + if (listener != &bp && injection_instr > 0) { result = param.msg.add_result(); handleEvent(*result, result->NOINJECTION, "WTF"); diff --git a/src/experiments/cored-voter/experiment.cc b/src/experiments/cored-voter/experiment.cc index a09af3ad..75c9d16b 100644 --- a/src/experiments/cored-voter/experiment.cc +++ b/src/experiments/cored-voter/experiment.cc @@ -349,11 +349,11 @@ bool CoredVoter::run() { // Fast forward to injection address m_log << "Trying to inject @ instr #" << dec << injection_instr << endl; - if ((injection_instr + 2) > 0) { + if (injection_instr > 0) { simulator.clearListeners(); BPSingleListener bp; bp.setWatchInstructionPointer(ANY_ADDR); - bp.setCounter(injection_instr + 2); // FIXME: FISHY! + bp.setCounter(injection_instr); simulator.addListener(&bp); fail::BaseListener * listener = simulator.resume(); diff --git a/src/experiments/dciao-kernelstructs/experiment.cc b/src/experiments/dciao-kernelstructs/experiment.cc index f3bb3da2..1b360e9f 100644 --- a/src/experiments/dciao-kernelstructs/experiment.cc +++ b/src/experiments/dciao-kernelstructs/experiment.cc @@ -197,7 +197,7 @@ bool DCIAOKernelStructs::run() { simulator.addListener(&l_time_marker_print); bp.setWatchInstructionPointer(ANY_ADDR); - bp.setCounter(injection_instr+1); + bp.setCounter(injection_instr); simulator.addListener(&bp); // Add vport listener diff --git a/src/experiments/fiascoFail/experiment.cc b/src/experiments/fiascoFail/experiment.cc index b9cac1c4..16237200 100644 --- a/src/experiments/fiascoFail/experiment.cc +++ b/src/experiments/fiascoFail/experiment.cc @@ -253,7 +253,7 @@ bool FiascoFailExperiment::faultInjection() if(instr_offset > 0) { 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 BaseListener *go = waitIOOrOther(true); // Resume simulation and log VGA-Output diff --git a/src/experiments/kesogc/experiment.cc b/src/experiments/kesogc/experiment.cc index 19f60219..30d0eacb 100644 --- a/src/experiments/kesogc/experiment.cc +++ b/src/experiments/kesogc/experiment.cc @@ -187,8 +187,7 @@ bool KESOgc::run() BPSingleListener bp; bp.setWatchInstructionPointer(ANY_ADDR); - // Fix offset by 1 error - bp.setCounter(injection_instr + 1); + bp.setCounter(injection_instr); simulator.addListener(&bp); diff --git a/src/experiments/kesorefs/experiment.cc b/src/experiments/kesorefs/experiment.cc index 0e1e9a84..ef39088f 100644 --- a/src/experiments/kesorefs/experiment.cc +++ b/src/experiments/kesorefs/experiment.cc @@ -161,7 +161,7 @@ bool KESOrefs::run() BPSingleListener bp; bp.setWatchInstructionPointer(ANY_ADDR); - bp.setCounter(injection_instr + 1); + bp.setCounter(injection_instr); simulator.addListener(&bp); bool inject = true; diff --git a/src/experiments/vezs-example/experiment.cc b/src/experiments/vezs-example/experiment.cc index d5267793..b0759f85 100644 --- a/src/experiments/vezs-example/experiment.cc +++ b/src/experiments/vezs-example/experiment.cc @@ -160,8 +160,7 @@ bool VEZSExperiment::run() BPSingleListener bp; bp.setWatchInstructionPointer(ANY_ADDR); - // Fix offset by 1 error - bp.setCounter(injection_instr + 1); + bp.setCounter(injection_instr); simulator.addListener(&bp);