From 91a9c6f688994daddea14309515ca55931f29cf3 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Fri, 27 Feb 2015 19:34:38 +0100 Subject: [PATCH] core/sal: restore() more reliable for bochs BochsController::restore() now recreates a state more expectable from the experiment. The state is now the same that save() leaves behind in its most prominent use case after hitting a breakpoint. This change breaks backwards compatibility with some experiments, see below! Right after a breakpoint on a specific address fired and BochsController::save() was called, another breakpoint on that specific address would not fire again (unless that instruction is executed again later on). Up to this change, the situation after calling BochsController::restore() was different: A breakpoint on that specific address would fire twice. This difference led to the problem that running the tracing plugin after save() would work fine (recording the current instruction once, since 3dc752c "tracing: fix loss of first dynamic instruction"), but running it after restore() would record the current instruction *twice*. This change aligns restore()'s behavior to that of save(). The implications for existing experiments, traces and results are: - Existing result data should be not affected at all, as trace.time1/time2 were correct before this change. Nevertheless, the assumption time2-time1 >= instr2-instr1 does not hold for equivalence classes including the first instruction, if the latter was faultily recorded twice (see below). - Existing traces that were recorded after a restore() (with a tracing plugin including the aforementioned commit 3dc752c) contain the first instruction twice. An affected trace can be corrected with this command line: dump-trace old.tc | tail -n +2 | convert-trace -f dump -t new.tc - For experiments that record traces after a restore() (such as ecos_kernel_test), nothing changes, as both the tracing and the fast-forwarding before the fault injection now see one instruction event less. - Experiments that record traces after a save(), especially those that rely on the generic-tracing experiment for tracing, now see one instruction event less, before they need to inject their fault. These experiments need to be adjusted, for example dciao-kernelstructs now should use bp.setCounter(injection_instr) instead of bp.setCounter(injection_instr+1). Change-Id: I913bed9f1cad91ed3025f610024d62cfc2b9b11b --- src/core/sal/bochs/BochsController.cc | 3 ++- src/core/sal/bochs/FailBochsGlobals.hpp | 1 + src/core/sal/bochs/RestoreState.ah | 22 +++++++++++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) 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();