Fail* directories reorganized, Code-cleanup (-> coding-style), Typos+comments fixed.
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1321 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
31
src/experiments/cool-checksum/CMakeLists.txt
Normal file
31
src/experiments/cool-checksum/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
set(EXPERIMENT_NAME cool-checksum)
|
||||
set(EXPERIMENT_TYPE CoolChecksumExperiment)
|
||||
configure_file(../instantiate-experiment.ah.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
|
||||
)
|
||||
|
||||
## Setup desired protobuf descriptions HERE ##
|
||||
set(MY_PROTOS
|
||||
coolchecksum.proto
|
||||
)
|
||||
|
||||
set(MY_CAMPAIGN_SRCS
|
||||
experiment.hpp
|
||||
experiment.cc
|
||||
campaign.hpp
|
||||
campaign.cc
|
||||
)
|
||||
|
||||
#### PROTOBUFS ####
|
||||
find_package(Protobuf REQUIRED)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
|
||||
|
||||
## Build library
|
||||
add_library(${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS})
|
||||
|
||||
## This is the example's campaign server distributing experiment parameters
|
||||
add_executable(${EXPERIMENT_NAME}-server main.cc)
|
||||
target_link_libraries(${EXPERIMENT_NAME}-server ${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY})
|
||||
272
src/experiments/cool-checksum/campaign.cc
Normal file
272
src/experiments/cool-checksum/campaign.cc
Normal file
@ -0,0 +1,272 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "campaign.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "cpn/CampaignManager.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
#include "util/ProtoStream.hpp"
|
||||
#include "sal/SALConfig.hpp"
|
||||
|
||||
#if COOL_FAULTSPACE_PRUNING
|
||||
#include "../plugins/tracing/TracingPlugin.hpp"
|
||||
char const * const trace_filename = "trace.pb";
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace fail;
|
||||
|
||||
char const * const results_csv = "coolcampaign.csv";
|
||||
|
||||
// equivalence class type: addr, [i1, i2]
|
||||
// addr: byte to inject a bit-flip into
|
||||
// [i1, i2]: interval of instruction numbers, counted from experiment
|
||||
// begin
|
||||
struct equivalence_class {
|
||||
unsigned byte_offset;
|
||||
int instr1, instr2;
|
||||
address_t instr2_absolute; // FIXME we could record them all here
|
||||
};
|
||||
|
||||
bool CoolChecksumCampaign::run()
|
||||
{
|
||||
Logger log("CoolChecksumCampaign");
|
||||
|
||||
ifstream test(results_csv);
|
||||
if (test.is_open()) {
|
||||
log << results_csv << " already exists" << endl;
|
||||
return false;
|
||||
}
|
||||
ofstream results(results_csv);
|
||||
if (!results.is_open()) {
|
||||
log << "failed to open " << results_csv << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
#if !COOL_FAULTSPACE_PRUNING
|
||||
int count = 0;
|
||||
for (int bit_offset = 0; bit_offset < COOL_ECC_OBJUNDERTEST_SIZE*8; ++bit_offset) {
|
||||
for (int instr_offset = 0; instr_offset < COOL_ECC_NUMINSTR; ++instr_offset) {
|
||||
CoolChecksumExperimentData *d = new CoolChecksumExperimentData;
|
||||
d->msg.set_instr_offset(instr_offset);
|
||||
d->msg.set_bit_offset(bit_offset);
|
||||
|
||||
campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
campaignmanager.noMoreParameters();
|
||||
log << "done enqueueing parameter sets (" << count << ")." << endl;
|
||||
|
||||
// collect results
|
||||
CoolChecksumExperimentData *res;
|
||||
int rescount = 0;
|
||||
results << "injection_ip\tinstr_offset\tinjection_bit\tresulttype\tresultdata\terror_corrected\tdetails" << endl;
|
||||
while ((res = static_cast<CoolChecksumExperimentData *>(campaignmanager.getDone()))) {
|
||||
rescount++;
|
||||
|
||||
results
|
||||
<< res->msg.injection_ip() << "\t"
|
||||
<< res->msg.instr_offset() << "\t"
|
||||
<< res->msg.bit_offset() << "\t"
|
||||
<< res->msg.resulttype() << "\t"
|
||||
<< res->msg.resultdata() << "\t"
|
||||
<< res->msg.error_corrected() << "\t"
|
||||
<< res->msg.details() << "\n";
|
||||
delete res;
|
||||
}
|
||||
#else
|
||||
// load trace
|
||||
ifstream tracef(trace_filename);
|
||||
if (tracef.fail()) {
|
||||
log << "couldn't open " << trace_filename << endl;
|
||||
return false;
|
||||
}
|
||||
ProtoIStream ps(&tracef);
|
||||
|
||||
// set of equivalence classes that need one (rather: eight, one for
|
||||
// each bit in that byte) experiment to determine them all
|
||||
vector<equivalence_class> ecs_need_experiment;
|
||||
// set of equivalence classes that need no experiment, because we know
|
||||
// they'd be identical to the golden run
|
||||
vector<equivalence_class> ecs_no_effect;
|
||||
|
||||
equivalence_class current_ec;
|
||||
|
||||
// for every injection address ...
|
||||
// XXX in more complex cases we'll need to iterate over a MemoryMap here
|
||||
for (unsigned byte_offset = 0; byte_offset < COOL_ECC_OBJUNDERTEST_SIZE; ++byte_offset) {
|
||||
|
||||
current_ec.instr1 = 0;
|
||||
// for every section in the trace between subsequent memory
|
||||
// accesses to that address ...
|
||||
// XXX reorganizing the trace for efficient seeks could speed this up
|
||||
int instr = 0;
|
||||
address_t instr_absolute = 0; // FIXME this one probably should also be recorded ...
|
||||
Trace_Event ev;
|
||||
ps.reset();
|
||||
|
||||
while(ps.getNext(&ev)) {
|
||||
// only count instruction events
|
||||
if (!ev.has_memaddr()) {
|
||||
// new instruction
|
||||
instr++;
|
||||
instr_absolute = ev.ip();
|
||||
continue;
|
||||
|
||||
// skip accesses to other data
|
||||
} else if (ev.memaddr() != byte_offset + COOL_ECC_OBJUNDERTEST) {
|
||||
continue;
|
||||
|
||||
// skip zero-sized intervals: these can
|
||||
// occur when an instruction accesses a
|
||||
// memory location more than once
|
||||
// (e.g., INC, CMPXCHG)
|
||||
} else if (current_ec.instr1 > instr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// we now have an interval-terminating R/W
|
||||
// event to the memaddr we're currently looking
|
||||
// at:
|
||||
|
||||
// complete the equivalence interval
|
||||
current_ec.instr2 = instr;
|
||||
current_ec.instr2_absolute = instr_absolute;
|
||||
current_ec.byte_offset = byte_offset;
|
||||
|
||||
if (ev.accesstype() == ev.READ) {
|
||||
// a sequence ending with READ: we need
|
||||
// to do one experiment to cover it
|
||||
// completely
|
||||
ecs_need_experiment.push_back(current_ec);
|
||||
} else if (ev.accesstype() == ev.WRITE) {
|
||||
// a sequence ending with WRITE: an
|
||||
// injection anywhere here would have
|
||||
// no effect.
|
||||
ecs_no_effect.push_back(current_ec);
|
||||
} else {
|
||||
log << "WAT" << endl;
|
||||
}
|
||||
|
||||
// next interval must start at next
|
||||
// instruction; the aforementioned
|
||||
// skipping mechanism wouldn't work
|
||||
// otherwise
|
||||
current_ec.instr1 = instr + 1;
|
||||
}
|
||||
|
||||
// close the last interval:
|
||||
// Why -1? In most cases it does not make sense to inject before the
|
||||
// very last instruction, as we won't execute it anymore. This *only*
|
||||
// makes sense if we also inject into parts of the result vector. This
|
||||
// is not the case in this experiment, and with -1 we'll get a
|
||||
// result comparable to the non-pruned campaign.
|
||||
current_ec.instr2 = instr - 1;
|
||||
current_ec.instr2_absolute = 0; // won't be used
|
||||
current_ec.byte_offset = byte_offset;
|
||||
// zero-sized? skip.
|
||||
if (current_ec.instr1 > current_ec.instr2) {
|
||||
continue;
|
||||
}
|
||||
// as the experiment ends, this byte is a "don't care":
|
||||
ecs_no_effect.push_back(current_ec);
|
||||
}
|
||||
|
||||
log << "equivalence classes generated:"
|
||||
<< " need_experiment = " << ecs_need_experiment.size()
|
||||
<< " no_effect = " << ecs_no_effect.size() << endl;
|
||||
|
||||
// statistics
|
||||
int num_dumb_experiments = 0;
|
||||
for (vector<equivalence_class>::const_iterator it = ecs_need_experiment.begin();
|
||||
it != ecs_need_experiment.end(); ++it) {
|
||||
num_dumb_experiments += (*it).instr2 - (*it).instr1 + 1;
|
||||
}
|
||||
for (vector<equivalence_class>::const_iterator it = ecs_no_effect.begin();
|
||||
it != ecs_no_effect.end(); ++it) {
|
||||
num_dumb_experiments += (*it).instr2 - (*it).instr1 + 1;
|
||||
}
|
||||
log << "pruning: reduced " << num_dumb_experiments * 8 <<
|
||||
" experiments to " << ecs_need_experiment.size() * 8 << endl;
|
||||
|
||||
// map for efficient access when results come in
|
||||
map<CoolChecksumExperimentData *, equivalence_class *> experiment_ecs;
|
||||
int count = 0;
|
||||
for (vector<equivalence_class>::iterator it = ecs_need_experiment.begin();
|
||||
it != ecs_need_experiment.end(); ++it) {
|
||||
for (int bitnr = 0; bitnr < 8; ++bitnr) {
|
||||
CoolChecksumExperimentData *d = new CoolChecksumExperimentData;
|
||||
// we pick the rightmost instruction in that interval
|
||||
d->msg.set_instr_offset((*it).instr2);
|
||||
d->msg.set_instr_address((*it).instr2_absolute);
|
||||
d->msg.set_bit_offset((*it).byte_offset * 8 + bitnr);
|
||||
|
||||
experiment_ecs[d] = &(*it);
|
||||
|
||||
campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
campaignmanager.noMoreParameters();
|
||||
log << "done enqueueing parameter sets (" << count << ")." << endl;
|
||||
|
||||
// CSV header
|
||||
results << "injection_ip\tinstr_offset\tinjection_bit\tresulttype\tresultdata\terror_corrected\tdetails" << endl;
|
||||
|
||||
// store no-effect "experiment" results
|
||||
// (for comparison reasons; we'll store that more compactly later)
|
||||
for (vector<equivalence_class>::const_iterator it = ecs_no_effect.begin();
|
||||
it != ecs_no_effect.end(); ++it) {
|
||||
for (int bitnr = 0; bitnr < 8; ++bitnr) {
|
||||
for (int instr = (*it).instr1; instr <= (*it).instr2; ++instr) {
|
||||
results
|
||||
<< (*it).instr2_absolute << "\t" // incorrect in all but one case!
|
||||
<< instr << "\t"
|
||||
<< ((*it).byte_offset * 8 + bitnr) << "\t"
|
||||
<< "1" << "\t"
|
||||
<< "45" << "\t"
|
||||
<< "0" << "\t"
|
||||
<< "" << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collect results
|
||||
CoolChecksumExperimentData *res;
|
||||
int rescount = 0;
|
||||
while ((res = static_cast<CoolChecksumExperimentData *>(campaignmanager.getDone()))) {
|
||||
rescount++;
|
||||
|
||||
equivalence_class *ec = experiment_ecs[res];
|
||||
|
||||
// sanity check
|
||||
if (ec->instr2 != res->msg.instr_offset()) {
|
||||
results << "WTF" << endl;
|
||||
log << "WTF" << endl;
|
||||
delete res;
|
||||
continue;
|
||||
}
|
||||
|
||||
// explode equivalence class to single "experiments"
|
||||
// (for comparison reasons; we'll store that more compactly later)
|
||||
for (int instr = ec->instr1; instr <= ec->instr2; ++instr) {
|
||||
results
|
||||
<< res->msg.injection_ip() << "\t" // incorrect in all but one case!
|
||||
<< instr << "\t"
|
||||
<< res->msg.bit_offset() << "\t"
|
||||
<< res->msg.resulttype() << "\t"
|
||||
<< res->msg.resultdata() << "\t"
|
||||
<< res->msg.error_corrected() << "\t"
|
||||
<< res->msg.details() << "\n";
|
||||
}
|
||||
delete res;
|
||||
}
|
||||
#endif
|
||||
log << "done. sent " << count << " received " << rescount << endl;
|
||||
results.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
19
src/experiments/cool-checksum/campaign.hpp
Normal file
19
src/experiments/cool-checksum/campaign.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef __COOLCAMPAIGN_HPP__
|
||||
#define __COOLCAMPAIGN_HPP__
|
||||
|
||||
#include "cpn/Campaign.hpp"
|
||||
#include "comm/ExperimentData.hpp"
|
||||
#include "coolchecksum.pb.h"
|
||||
|
||||
class CoolChecksumExperimentData : public fail::ExperimentData {
|
||||
public:
|
||||
CoolChecksumProtoMsg msg;
|
||||
CoolChecksumExperimentData() : fail::ExperimentData(&msg) {}
|
||||
};
|
||||
|
||||
class CoolChecksumCampaign : public fail::Campaign {
|
||||
public:
|
||||
virtual bool run();
|
||||
};
|
||||
|
||||
#endif // __COOLCAMPAIGN_HPP__
|
||||
29
src/experiments/cool-checksum/coolchecksum.proto
Normal file
29
src/experiments/cool-checksum/coolchecksum.proto
Normal file
@ -0,0 +1,29 @@
|
||||
message CoolChecksumProtoMsg {
|
||||
// parameters
|
||||
required int32 instr_offset = 1;
|
||||
optional int32 instr_address = 8; // for sanity checks
|
||||
required int32 bit_offset = 2;
|
||||
|
||||
// results
|
||||
// make these optional to reduce overhead for server->client communication
|
||||
enum ResultType {
|
||||
CALCDONE = 1;
|
||||
TIMEOUT = 2;
|
||||
TRAP = 3;
|
||||
UNKNOWN = 4;
|
||||
}
|
||||
// instruction pointer where injection was done
|
||||
optional uint32 injection_ip = 3;
|
||||
// result type, see above
|
||||
optional ResultType resulttype = 4;
|
||||
// result data, depending on resulttype:
|
||||
// CALCDONE: resultdata = calculated value
|
||||
// TIMEOUT: resultdata = latest EIP
|
||||
// TRAP: resultdata = latest EIP
|
||||
// UNKNOWN: resultdata = latest EIP
|
||||
optional uint32 resultdata = 5;
|
||||
// did ECC correct the fault?
|
||||
optional int32 error_corrected = 6;
|
||||
// optional textual description of what happened
|
||||
optional string details = 7;
|
||||
}
|
||||
201
src/experiments/cool-checksum/experiment.cc
Normal file
201
src/experiments/cool-checksum/experiment.cc
Normal file
@ -0,0 +1,201 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "util/Logger.hpp"
|
||||
#include "experiment.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "campaign.hpp"
|
||||
#include "sal/SALConfig.hpp"
|
||||
#include "sal/SALInst.hpp"
|
||||
#include "sal/Memory.hpp"
|
||||
#include "sal/bochs/BochsRegister.hpp"
|
||||
#include "sal/Event.hpp"
|
||||
#include "config/FailConfig.hpp"
|
||||
|
||||
#if COOL_FAULTSPACE_PRUNING
|
||||
#include "../plugins/tracing/TracingPlugin.hpp"
|
||||
#endif
|
||||
|
||||
#include "coolchecksum.pb.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace fail;
|
||||
|
||||
// Check if configuration dependencies are satisfied:
|
||||
#if !defined(CONFIG_EVENT_BREAKPOINTS) || !defined(CONFIG_SR_RESTORE) || \
|
||||
!defined(CONFIG_SR_SAVE) || !defined(CONFIG_SUPPRESS_INTERRUPTS) || \
|
||||
!defined(CONFIG_EVENT_TRAP)
|
||||
#error This experiment needs: breakpoints, suppressed-interrupts, traps, save, and restore. Enable these in the configuration.
|
||||
#endif
|
||||
|
||||
bool CoolChecksumExperiment::run()
|
||||
{
|
||||
Logger log("CoolChecksum", false);
|
||||
BPSingleEvent bp;
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
#if 1
|
||||
// STEP 1: run until interesting function starts, and save state
|
||||
bp.setWatchInstructionPointer(COOL_ECC_FUNC_ENTRY);
|
||||
simulator.addEventAndWait(&bp);
|
||||
log << "test function entry reached, saving state" << endl;
|
||||
log << "EIP = " << hex << bp.getTriggerInstructionPointer() << " or " << simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
log << "error_corrected = " << dec << ((int)simulator.getMemoryManager().getByte(COOL_ECC_ERROR_CORRECTED)) << endl;
|
||||
simulator.save("coolecc.state");
|
||||
#elif 0
|
||||
|
||||
// STEP 2: determine # instructions from start to end
|
||||
log << "restoring state" << endl;
|
||||
simulator.restore("coolecc.state");
|
||||
log << "EIP = " << hex << simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
|
||||
#if COOL_FAULTSPACE_PRUNING
|
||||
// STEP 2.5: Additionally do a golden run with memory access tracing
|
||||
// for fault-space pruning. (optional!)
|
||||
log << "enabling tracing" << endl;
|
||||
TracingPlugin tp;
|
||||
|
||||
// restrict memory access logging to injection target
|
||||
MemoryMap mm;
|
||||
mm.add(COOL_ECC_OBJUNDERTEST, COOL_ECC_OBJUNDERTEST_SIZE);
|
||||
tp.restrictMemoryAddresses(&mm);
|
||||
|
||||
// record trace
|
||||
ofstream of("trace.pb");
|
||||
tp.setTraceFile(&of);
|
||||
|
||||
// this must be done *after* configuring the plugin:
|
||||
simulator.addFlow(&tp);
|
||||
#endif
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
simulator.addSuppressedInterrupt(0);
|
||||
|
||||
int count;
|
||||
bp.setWatchInstructionPointer(ANY_ADDR);
|
||||
for (count = 0; bp.getTriggerInstructionPointer() != COOL_ECC_CALCDONE; ++count) {
|
||||
simulator.addEventAndWait(&bp);
|
||||
// log << "EIP = " << hex << simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
}
|
||||
log << "test function calculation position reached after " << dec << count << " instructions" << endl;
|
||||
Register* reg = simulator.getRegisterManager().getRegister(RID_CDX);
|
||||
log << dec << reg->getName() << " = " << reg->getData() << endl;
|
||||
|
||||
#if COOL_FAULTSPACE_PRUNING
|
||||
simulator.removeFlow(&tp);
|
||||
|
||||
// serialize trace to file
|
||||
if (of.fail()) {
|
||||
log << "failed to write trace.pb" << endl;
|
||||
simulator.clearEvents(this);
|
||||
return false;
|
||||
}
|
||||
of.close();
|
||||
#endif
|
||||
|
||||
#elif 1
|
||||
// FIXME consider moving experiment repetition into Fail* or even the
|
||||
// SAL -- whether and how this is possible with the chosen backend is
|
||||
// backend specific
|
||||
for (int i = 0; i < 2000; ++i) {
|
||||
|
||||
// STEP 3: The actual experiment.
|
||||
log << "restoring state" << endl;
|
||||
simulator.restore("coolecc.state");
|
||||
|
||||
log << "asking job server for experiment parameters" << endl;
|
||||
CoolChecksumExperimentData param;
|
||||
if (!m_jc.getParam(param)) {
|
||||
log << "Dying." << endl;
|
||||
// communicate that we were told to die
|
||||
simulator.terminate(1);
|
||||
}
|
||||
int id = param.getWorkloadID();
|
||||
int instr_offset = param.msg.instr_offset();
|
||||
int bit_offset = param.msg.bit_offset();
|
||||
log << "job " << id << " instr " << instr_offset << " bit " << bit_offset << endl;
|
||||
|
||||
// FIXME could be improved (especially for backends supporting
|
||||
// breakpoints natively) by utilizing a previously recorded instruction
|
||||
// trace
|
||||
bp.setWatchInstructionPointer(ANY_ADDR);
|
||||
for (int count = 0; count < instr_offset; ++count) {
|
||||
simulator.addEventAndWait(&bp);
|
||||
}
|
||||
|
||||
// inject
|
||||
guest_address_t inject_addr = COOL_ECC_OBJUNDERTEST + bit_offset / 8;
|
||||
MemoryManager& mm = simulator.getMemoryManager();
|
||||
byte_t data = mm.getByte(inject_addr);
|
||||
byte_t newdata = data ^ (1 << (bit_offset % 8));
|
||||
mm.setByte(inject_addr, newdata);
|
||||
// note at what IP we did it
|
||||
int32_t injection_ip = simulator.getRegisterManager().getInstructionPointer();
|
||||
param.msg.set_injection_ip(injection_ip);
|
||||
log << "inject @ ip " << injection_ip
|
||||
<< " (offset " << dec << instr_offset << ")"
|
||||
<< " bit " << bit_offset << ": 0x"
|
||||
<< hex << ((int)data) << " -> 0x" << ((int)newdata) << endl;
|
||||
// sanity check (only works if we're working with an instruction trace)
|
||||
if (param.msg.has_instr_address() &&
|
||||
injection_ip != param.msg.instr_address()) {
|
||||
stringstream ss;
|
||||
ss << "SANITY CHECK FAILED: " << injection_ip
|
||||
<< " != " << param.msg.instr_address() << endl;
|
||||
log << ss.str();
|
||||
param.msg.set_resulttype(param.msg.UNKNOWN);
|
||||
param.msg.set_resultdata(injection_ip);
|
||||
param.msg.set_details(ss.str());
|
||||
|
||||
simulator.clearEvents();
|
||||
m_jc.sendResult(param);
|
||||
continue;
|
||||
}
|
||||
|
||||
// aftermath
|
||||
BPSingleEvent ev_done(COOL_ECC_CALCDONE);
|
||||
simulator.addEvent(&ev_done);
|
||||
BPSingleEvent ev_timeout(ANY_ADDR);
|
||||
ev_timeout.setCounter(COOL_ECC_NUMINSTR + 3000);
|
||||
simulator.addEvent(&ev_timeout);
|
||||
TrapEvent ev_trap(ANY_TRAP);
|
||||
simulator.addEvent(&ev_trap);
|
||||
|
||||
BaseEvent* ev = simulator.waitAny();
|
||||
if (ev == &ev_done) {
|
||||
Register* pRegRes = simulator.getRegisterManager().getRegister(RID_CDX);
|
||||
int32_t data = pRegRes->getData();
|
||||
log << dec << "Result " << pRegRes->getName() << " = " << data << endl;
|
||||
param.msg.set_resulttype(param.msg.CALCDONE);
|
||||
param.msg.set_resultdata(data);
|
||||
} else if (ev == &ev_timeout) {
|
||||
log << dec << "Result TIMEOUT" << endl;
|
||||
param.msg.set_resulttype(param.msg.TIMEOUT);
|
||||
param.msg.set_resultdata(simulator.getRegisterManager().getInstructionPointer());
|
||||
} else if (ev == &ev_trap) {
|
||||
log << dec << "Result TRAP #" << ev_trap.getTriggerNumber() << endl;
|
||||
param.msg.set_resulttype(param.msg.TRAP);
|
||||
param.msg.set_resultdata(simulator.getRegisterManager().getInstructionPointer());
|
||||
} else {
|
||||
log << dec << "Result WTF?" << endl;
|
||||
param.msg.set_resulttype(param.msg.UNKNOWN);
|
||||
param.msg.set_resultdata(simulator.getRegisterManager().getInstructionPointer());
|
||||
|
||||
stringstream ss;
|
||||
ss << "eventid " << ev << " EIP " << simulator.getRegisterManager().getInstructionPointer();
|
||||
param.msg.set_details(ss.str());
|
||||
}
|
||||
simulator.clearEvents();
|
||||
int32_t error_corrected = simulator.getMemoryManager().getByte(COOL_ECC_ERROR_CORRECTED);
|
||||
param.msg.set_error_corrected(error_corrected);
|
||||
m_jc.sendResult(param);
|
||||
}
|
||||
|
||||
// we do not want the simulator to continue running, especially for
|
||||
// headless and distributed experiments
|
||||
simulator.terminate();
|
||||
#endif
|
||||
// simulator continues to run
|
||||
simulator.clearEvents(this);
|
||||
return true;
|
||||
}
|
||||
14
src/experiments/cool-checksum/experiment.hpp
Normal file
14
src/experiments/cool-checksum/experiment.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __COOLEXPERIMENT_HPP__
|
||||
#define __COOLEXPERIMENT_HPP__
|
||||
|
||||
#include "efw/ExperimentFlow.hpp"
|
||||
#include "efw/JobClient.hpp"
|
||||
|
||||
class CoolChecksumExperiment : public fail::ExperimentFlow {
|
||||
fail::JobClient m_jc;
|
||||
public:
|
||||
CoolChecksumExperiment() : m_jc("ios.cs.tu-dortmund.de") {}
|
||||
bool run();
|
||||
};
|
||||
|
||||
#endif // __COOLEXPERIMENT_HPP__
|
||||
40
src/experiments/cool-checksum/experimentInfo.hpp
Normal file
40
src/experiments/cool-checksum/experimentInfo.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef __EXPERIMENT_INFO_HPP__
|
||||
#define __EXPERIMENT_INFO_HPP__
|
||||
|
||||
#define COOL_FAULTSPACE_PRUNING 0
|
||||
|
||||
// FIXME autogenerate this
|
||||
|
||||
#if 1 // with ECC
|
||||
|
||||
// the task function's entry address:
|
||||
// nm -C ecc.elf|fgrep Alpha::functionTaskTask0
|
||||
#define COOL_ECC_FUNC_ENTRY 0x00200b32
|
||||
// one of the last instructions before the task calls printf:
|
||||
// (objdump -Cd ecc.elf|less)
|
||||
#define COOL_ECC_CALCDONE 0x00200bdf
|
||||
// number of instructions the target executes under non-error conditions from ENTRY to CALCDONE:
|
||||
// (result of experiment's step #2)
|
||||
#define COOL_ECC_NUMINSTR 1995
|
||||
// the ECC protected object's address:
|
||||
// nm -C ecc.elf|fgrep objectUnderTest
|
||||
#define COOL_ECC_OBJUNDERTEST 0x002127a4
|
||||
// the ECC protected object's payload size:
|
||||
// (we know that from the object's definition and usual memory layout)
|
||||
#define COOL_ECC_OBJUNDERTEST_SIZE 10
|
||||
// the variable that's increased if ECC corrects an error:
|
||||
// nm -C ecc.elf|fgrep error_corrected
|
||||
#define COOL_ECC_ERROR_CORRECTED 0x002127b0
|
||||
|
||||
#else // without ECC
|
||||
|
||||
#define COOL_ECC_FUNC_ENTRY 0x00200a90
|
||||
#define COOL_ECC_CALCDONE 0x00200ab7
|
||||
#define COOL_ECC_NUMINSTR 97
|
||||
#define COOL_ECC_OBJUNDERTEST 0x0021263c
|
||||
#define COOL_ECC_OBJUNDERTEST_SIZE 10
|
||||
#define COOL_ECC_ERROR_CORRECTED 0x002127b0 // dummy
|
||||
|
||||
#endif
|
||||
|
||||
#endif // __EXPERIMENT_INFO_HPP__
|
||||
15
src/experiments/cool-checksum/main.cc
Normal file
15
src/experiments/cool-checksum/main.cc
Normal file
@ -0,0 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cpn/CampaignManager.hpp"
|
||||
#include "campaign.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CoolChecksumCampaign c;
|
||||
if (fail::campaignmanager.runCampaign(&c)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user