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, since3dc752c"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 commit3dc752c) 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
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
Reference in New Issue
Block a user