Files
fail/src/core/sal/bochs/RestoreState.ah
Horst Schirmeier 91a9c6f688 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
2015-03-06 08:38:40 +01:00

48 lines
1.3 KiB
Plaintext

#ifndef __RESTORE_STATE_AH__
#define __RESTORE_STATE_AH__
#include "config/VariantConfig.hpp"
#include "config/FailConfig.hpp"
#if defined(BUILD_BOCHS) && defined(CONFIG_SR_RESTORE)
#include <iostream>
#include "bochs.h"
#include "../SALInst.hpp"
aspect RestoreState {
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();
}
};
#endif // CONFIG_SR_RESTORE
#endif // __RESTORE_STATE_AH__