ecos: guest-image independent fail client
TODO: campaign needs to be updated, too git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1908 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -57,8 +57,9 @@ bool EcosKernelTestCampaign::writeTraceInfo(unsigned instr_counter, unsigned tim
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EcosKernelTestCampaign::readTraceInfo(unsigned &instr_counter, unsigned &timeout, unsigned &lowest_addr, unsigned &highest_addr) {
|
bool EcosKernelTestCampaign::readTraceInfo(unsigned &instr_counter, unsigned &timeout, unsigned &lowest_addr, unsigned &highest_addr,
|
||||||
ifstream file(filename_traceinfo().c_str());
|
const std::string& variant, const std::string& benchmark) {
|
||||||
|
ifstream file(filename_traceinfo(variant, benchmark).c_str());
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
cout << "failed to open " << filename_traceinfo() << endl;
|
cout << "failed to open " << filename_traceinfo() << endl;
|
||||||
return false;
|
return false;
|
||||||
@ -127,6 +128,14 @@ std::string EcosKernelTestCampaign::filename_results(const std::string& variant,
|
|||||||
return dir_results + "/" + variant + "_" + benchmark + "_" + "results.csv";
|
return dir_results + "/" + variant + "_" + benchmark + "_" + "results.csv";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string EcosKernelTestCampaign::filename_elf(const std::string& variant, const std::string& benchmark)
|
||||||
|
{
|
||||||
|
if (variant.size() && benchmark.size()) {
|
||||||
|
return dir_images + "/" + variant + "/" + benchmark + ".elf";
|
||||||
|
}
|
||||||
|
return "kernel.elf";
|
||||||
|
}
|
||||||
|
|
||||||
// equivalence class type: addr, [i1, i2]
|
// equivalence class type: addr, [i1, i2]
|
||||||
// addr: byte to inject a bit-flip into
|
// addr: byte to inject a bit-flip into
|
||||||
// [i1, i2]: interval of instruction numbers, counted from experiment
|
// [i1, i2]: interval of instruction numbers, counted from experiment
|
||||||
@ -355,6 +364,9 @@ bool EcosKernelTestCampaign::run()
|
|||||||
// instantly enqueue job: that way the job clients can already
|
// instantly enqueue job: that way the job clients can already
|
||||||
// start working in parallel
|
// start working in parallel
|
||||||
EcosKernelTestExperimentData *d = new EcosKernelTestExperimentData;
|
EcosKernelTestExperimentData *d = new EcosKernelTestExperimentData;
|
||||||
|
// FIXME use correct variant/benchmark
|
||||||
|
d->msg.set_variant("");
|
||||||
|
d->msg.set_benchmark("");
|
||||||
// we pick the rightmost instruction in that interval
|
// we pick the rightmost instruction in that interval
|
||||||
d->msg.set_instr_offset(current_ec.instr2);
|
d->msg.set_instr_offset(current_ec.instr2);
|
||||||
d->msg.set_instr_address(current_ec.instr2_absolute);
|
d->msg.set_instr_address(current_ec.instr2_absolute);
|
||||||
@ -460,7 +472,7 @@ bool EcosKernelTestCampaign::run()
|
|||||||
" experiments to " << ecs_need_experiment.size() * 8 << endl;
|
" experiments to " << ecs_need_experiment.size() * 8 << endl;
|
||||||
|
|
||||||
// CSV header
|
// CSV header
|
||||||
results << "ec_instr1\tec_instr2\tec_instr2_absolute\tec_data_address\tbitnr\tbit_width\tresulttype\tecos_test_result\tlatest_ip\terror_corrected\tdetails" << endl;
|
results << "variant\tbenchmark\tec_instr1\tec_instr2\tec_instr2_absolute\tec_data_address\tbitnr\tbit_width\tresulttype\tecos_test_result\tlatest_ip\terror_corrected\tdetails" << endl;
|
||||||
|
|
||||||
// store no-effect "experiment" results
|
// store no-effect "experiment" results
|
||||||
for (vector<equivalence_class>::const_iterator it = ecs_no_effect.begin();
|
for (vector<equivalence_class>::const_iterator it = ecs_no_effect.begin();
|
||||||
@ -509,6 +521,8 @@ bool EcosKernelTestCampaign::run()
|
|||||||
for (int idx = 0; idx < res->msg.result_size(); ++idx) {
|
for (int idx = 0; idx < res->msg.result_size(); ++idx) {
|
||||||
results
|
results
|
||||||
// repeated for all single experiments:
|
// repeated for all single experiments:
|
||||||
|
<< res->msg.variant() << "\t"
|
||||||
|
<< res->msg.benchmark() << "\t"
|
||||||
<< ec.instr1 << "\t"
|
<< ec.instr1 << "\t"
|
||||||
<< ec.instr2 << "\t"
|
<< ec.instr2 << "\t"
|
||||||
<< ec.instr2_absolute << "\t"
|
<< ec.instr2_absolute << "\t"
|
||||||
|
|||||||
@ -21,11 +21,11 @@ public:
|
|||||||
virtual bool run();
|
virtual bool run();
|
||||||
static bool readMemoryMap(fail::MemoryMap &mm, char const * const filename);
|
static bool readMemoryMap(fail::MemoryMap &mm, char const * const filename);
|
||||||
static bool writeTraceInfo(unsigned instr_counter, unsigned timeout, unsigned lowest_addr, unsigned highest_addr);
|
static bool writeTraceInfo(unsigned instr_counter, unsigned timeout, unsigned lowest_addr, unsigned highest_addr);
|
||||||
static bool readTraceInfo(unsigned &instr_counter, unsigned &timeout, unsigned &lowest_addr, unsigned &highest_addr);
|
static bool readTraceInfo(unsigned &instr_counter, unsigned &timeout, unsigned &lowest_addr, unsigned &highest_addr, const std::string& variant = "", const std::string& benchmark = "");
|
||||||
static std::string filename_memorymap(const std::string& variant = "", const std::string& benchmark = "");
|
static std::string filename_memorymap(const std::string& variant = "", const std::string& benchmark = "");
|
||||||
static std::string filename_state(const std::string& variant = "", const std::string& benchmark = "");
|
static std::string filename_state(const std::string& variant = "", const std::string& benchmark = "");
|
||||||
static std::string filename_trace(const std::string& variant = "", const std::string& benchmark = "");
|
static std::string filename_trace(const std::string& variant = "", const std::string& benchmark = "");
|
||||||
static std::string filename_traceinfo(const std::string& variant = "", const std::string& benchmark = "");
|
static std::string filename_traceinfo(const std::string& variant = "", const std::string& benchmark = "");
|
||||||
static std::string filename_results(const std::string& variant, const std::string& benchmark);
|
static std::string filename_results(const std::string& variant, const std::string& benchmark);
|
||||||
|
static std::string filename_elf(const std::string& variant = "", const std::string& benchmark = "");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,12 +2,17 @@ message EcosKernelTestProtoMsg {
|
|||||||
// Input: experiment parameters
|
// Input: experiment parameters
|
||||||
// (client executes 8 experiments, one for each bit at mem_addr)
|
// (client executes 8 experiments, one for each bit at mem_addr)
|
||||||
|
|
||||||
|
// EDM/ERM variant
|
||||||
|
required string variant = 1;
|
||||||
|
// benchmark
|
||||||
|
required string benchmark = 2;
|
||||||
|
|
||||||
// FI at #instructions from experiment start
|
// FI at #instructions from experiment start
|
||||||
required int32 instr_offset = 1;
|
required int32 instr_offset = 3;
|
||||||
// the exact IP value at this point in time (from golden run)
|
// the exact IP value at this point in time (from golden run)
|
||||||
optional int32 instr_address = 2; // for sanity checks
|
optional int32 instr_address = 4; // for sanity checks
|
||||||
// address of the byte to inject bit-flips
|
// address of the byte to inject bit-flips
|
||||||
required int32 mem_addr = 3;
|
required int32 mem_addr = 5;
|
||||||
|
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
|
|
||||||
@ -15,9 +20,9 @@ message EcosKernelTestProtoMsg {
|
|||||||
|
|
||||||
// IP where we did the injection: for debugging purposes, must be identical
|
// IP where we did the injection: for debugging purposes, must be identical
|
||||||
// to instr_address
|
// to instr_address
|
||||||
optional int32 injection_ip = 4;
|
optional int32 injection_ip = 6;
|
||||||
|
|
||||||
repeated group Result = 5 {
|
repeated group Result = 7 {
|
||||||
// single experiment bit offset
|
// single experiment bit offset
|
||||||
required int32 bit_offset = 1;
|
required int32 bit_offset = 1;
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#include "sal/bochs/BochsRegister.hpp"
|
#include "sal/bochs/BochsRegister.hpp"
|
||||||
#include "sal/bochs/BochsListener.hpp"
|
#include "sal/bochs/BochsListener.hpp"
|
||||||
#include "sal/Listener.hpp"
|
#include "sal/Listener.hpp"
|
||||||
|
#include "util/ElfReader.hpp"
|
||||||
|
|
||||||
// You need to have the tracing plugin enabled for this
|
// You need to have the tracing plugin enabled for this
|
||||||
#include "../plugins/tracing/TracingPlugin.hpp"
|
#include "../plugins/tracing/TracingPlugin.hpp"
|
||||||
@ -36,12 +37,12 @@ using namespace fail;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PREREQUISITES
|
#if PREREQUISITES
|
||||||
bool EcosKernelTestExperiment::retrieveGuestAddresses() {
|
bool EcosKernelTestExperiment::retrieveGuestAddresses(guest_address_t addr_finish) {
|
||||||
log << "STEP 0: record memory map with addresses of 'interesting' objects" << endl;
|
log << "STEP 0: record memory map with addresses of 'interesting' objects" << endl;
|
||||||
|
|
||||||
// run until 'ECOS_FUNC_FINISH' is reached
|
// run until func_finish is reached
|
||||||
BPSingleListener bp;
|
BPSingleListener bp;
|
||||||
bp.setWatchInstructionPointer(ECOS_FUNC_FINISH);
|
bp.setWatchInstructionPointer(addr_finish);
|
||||||
|
|
||||||
// memory map serialization
|
// memory map serialization
|
||||||
ofstream mm(EcosKernelTestCampaign::filename_memorymap().c_str(), ios::out);
|
ofstream mm(EcosKernelTestCampaign::filename_memorymap().c_str(), ios::out);
|
||||||
@ -82,7 +83,7 @@ bool EcosKernelTestExperiment::retrieveGuestAddresses() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(number_of_guest_events > 0);
|
assert(number_of_guest_events > 0);
|
||||||
log << "Breakpoint at 'ECOS_FUNC_FINISH' reached: created memory map (" << number_of_guest_events << " entries)" << endl;
|
log << "Breakpoint at func_finish reached: created memory map (" << number_of_guest_events << " entries)" << endl;
|
||||||
delete str;
|
delete str;
|
||||||
|
|
||||||
// close serialized mm
|
// close serialized mm
|
||||||
@ -94,7 +95,7 @@ bool EcosKernelTestExperiment::retrieveGuestAddresses() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EcosKernelTestExperiment::establishState() {
|
bool EcosKernelTestExperiment::establishState(guest_address_t addr_entry, guest_address_t addr_errors_corrected) {
|
||||||
log << "STEP 1: run until interesting function starts, and save state" << endl;
|
log << "STEP 1: run until interesting function starts, and save state" << endl;
|
||||||
|
|
||||||
GuestListener g;
|
GuestListener g;
|
||||||
@ -108,27 +109,27 @@ bool EcosKernelTestExperiment::establishState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BPSingleListener bp;
|
BPSingleListener bp;
|
||||||
bp.setWatchInstructionPointer(ECOS_FUNC_ENTRY);
|
bp.setWatchInstructionPointer(addr_entry);
|
||||||
simulator.addListenerAndResume(&bp);
|
simulator.addListenerAndResume(&bp);
|
||||||
log << "test function entry reached, saving state" << endl;
|
log << "test function entry reached, saving state" << endl;
|
||||||
log << "EIP = " << hex << bp.getTriggerInstructionPointer() << endl;
|
log << "EIP = " << hex << bp.getTriggerInstructionPointer() << endl;
|
||||||
//log << "error_corrected = " << dec << ((int)simulator.getMemoryManager().getByte(ECC_ERROR_CORRECTED)) << endl;
|
//log << "error_corrected = " << dec << ((int)simulator.getMemoryManager().getByte(addr_errors_corrected)) << endl;
|
||||||
simulator.save(EcosKernelTestCampaign::filename_state());
|
simulator.save(EcosKernelTestCampaign::filename_state());
|
||||||
assert(bp.getTriggerInstructionPointer() == ECOS_FUNC_ENTRY);
|
assert(bp.getTriggerInstructionPointer() == addr_entry);
|
||||||
assert(simulator.getRegisterManager().getInstructionPointer() == ECOS_FUNC_ENTRY);
|
assert(simulator.getRegisterManager().getInstructionPointer() == addr_entry);
|
||||||
|
|
||||||
// clean up simulator
|
// clean up simulator
|
||||||
simulator.clearListeners();
|
simulator.clearListeners();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EcosKernelTestExperiment::performTrace() {
|
bool EcosKernelTestExperiment::performTrace(guest_address_t addr_entry, guest_address_t addr_finish) {
|
||||||
log << "STEP 2: record trace for fault-space pruning" << endl;
|
log << "STEP 2: record trace for fault-space pruning" << endl;
|
||||||
|
|
||||||
log << "restoring state" << endl;
|
log << "restoring state" << endl;
|
||||||
simulator.restore(EcosKernelTestCampaign::filename_state());
|
simulator.restore(EcosKernelTestCampaign::filename_state());
|
||||||
log << "EIP = " << hex << simulator.getRegisterManager().getInstructionPointer() << endl;
|
log << "EIP = " << hex << simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||||
assert(simulator.getRegisterManager().getInstructionPointer() == ECOS_FUNC_ENTRY);
|
assert(simulator.getRegisterManager().getInstructionPointer() == addr_entry);
|
||||||
|
|
||||||
log << "enabling tracing" << endl;
|
log << "enabling tracing" << endl;
|
||||||
TracingPlugin tp;
|
TracingPlugin tp;
|
||||||
@ -148,7 +149,7 @@ bool EcosKernelTestExperiment::performTrace() {
|
|||||||
|
|
||||||
// again, run until 'ECOS_FUNC_FINISH' is reached
|
// again, run until 'ECOS_FUNC_FINISH' is reached
|
||||||
BPSingleListener bp;
|
BPSingleListener bp;
|
||||||
bp.setWatchInstructionPointer(ECOS_FUNC_FINISH);
|
bp.setWatchInstructionPointer(addr_finish);
|
||||||
simulator.addListener(&bp);
|
simulator.addListener(&bp);
|
||||||
|
|
||||||
// on the way, count instructions // FIXME add SAL functionality for this?
|
// on the way, count instructions // FIXME add SAL functionality for this?
|
||||||
@ -236,9 +237,11 @@ bool EcosKernelTestExperiment::performTrace() {
|
|||||||
bool EcosKernelTestExperiment::faultInjection() {
|
bool EcosKernelTestExperiment::faultInjection() {
|
||||||
log << "STEP 3: The actual experiment." << endl;
|
log << "STEP 3: The actual experiment." << endl;
|
||||||
|
|
||||||
// read trace info
|
// trace info
|
||||||
unsigned instr_counter, estimated_timeout, lowest_addr, highest_addr;
|
unsigned instr_counter, estimated_timeout, lowest_addr, highest_addr;
|
||||||
EcosKernelTestCampaign::readTraceInfo(instr_counter, estimated_timeout, lowest_addr, highest_addr);
|
// ELF symbol addresses
|
||||||
|
guest_address_t addr_entry, addr_finish, addr_test_output, addr_errors_corrected,
|
||||||
|
addr_panic, addr_text_start, addr_text_end;
|
||||||
|
|
||||||
BPSingleListener bp;
|
BPSingleListener bp;
|
||||||
|
|
||||||
@ -258,15 +261,24 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// XXX debug
|
// XXX debug
|
||||||
|
param.msg.set_variant("bitmap_CRC");
|
||||||
|
param.msg.set_benchmark("bin_sem0");
|
||||||
param.msg.set_instr_offset(7462);
|
param.msg.set_instr_offset(7462);
|
||||||
//param.msg.set_instr_address(12345);
|
//param.msg.set_instr_address(12345);
|
||||||
param.msg.set_mem_addr(44540);
|
param.msg.set_mem_addr(44540);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int id = param.getWorkloadID();
|
int id = param.getWorkloadID();
|
||||||
|
m_variant = param.msg.variant();
|
||||||
|
m_benchmark = param.msg.benchmark();
|
||||||
int instr_offset = param.msg.instr_offset();
|
int instr_offset = param.msg.instr_offset();
|
||||||
int mem_addr = param.msg.mem_addr();
|
int mem_addr = param.msg.mem_addr();
|
||||||
|
|
||||||
|
EcosKernelTestCampaign::readTraceInfo(instr_counter, estimated_timeout,
|
||||||
|
lowest_addr, highest_addr, m_variant, m_benchmark);
|
||||||
|
readELFSymbols(addr_entry, addr_finish, addr_test_output,
|
||||||
|
addr_errors_corrected, addr_panic, addr_text_start, addr_text_end);
|
||||||
|
|
||||||
// for each job we're actually doing *8* experiments (one for each bit)
|
// for each job we're actually doing *8* experiments (one for each bit)
|
||||||
for (int bit_offset = 0; bit_offset < 8; ++bit_offset) {
|
for (int bit_offset = 0; bit_offset < 8; ++bit_offset) {
|
||||||
// 8 results in one job
|
// 8 results in one job
|
||||||
@ -288,7 +300,7 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// reaching finish() could happen before OR after FI
|
// reaching finish() could happen before OR after FI
|
||||||
BPSingleListener func_finish(ECOS_FUNC_FINISH);
|
BPSingleListener func_finish(addr_finish);
|
||||||
simulator.addListener(&func_finish);
|
simulator.addListener(&func_finish);
|
||||||
|
|
||||||
// no need to wait if offset is 0
|
// no need to wait if offset is 0
|
||||||
@ -350,8 +362,8 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
simulator.addListener(&ev_trap);
|
simulator.addListener(&ev_trap);
|
||||||
|
|
||||||
// jump outside text segment
|
// jump outside text segment
|
||||||
BPRangeListener ev_below_text(ANY_ADDR, ECOS_TEXT_START - 1);
|
BPRangeListener ev_below_text(ANY_ADDR, addr_text_start - 1);
|
||||||
BPRangeListener ev_beyond_text(ECOS_TEXT_END + 1, ANY_ADDR);
|
BPRangeListener ev_beyond_text(addr_text_end + 1, ANY_ADDR);
|
||||||
simulator.addListener(&ev_below_text);
|
simulator.addListener(&ev_below_text);
|
||||||
simulator.addListener(&ev_beyond_text);
|
simulator.addListener(&ev_beyond_text);
|
||||||
|
|
||||||
@ -374,12 +386,14 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
//simulator.addListener(&ev_end);
|
//simulator.addListener(&ev_end);
|
||||||
|
|
||||||
// eCos' test output function, which will show if the test PASSed or FAILed
|
// eCos' test output function, which will show if the test PASSed or FAILed
|
||||||
BPSingleListener func_test_output(ECOS_FUNC_TEST_OUTPUT);
|
BPSingleListener func_test_output(addr_test_output);
|
||||||
simulator.addListener(&func_test_output);
|
simulator.addListener(&func_test_output);
|
||||||
|
|
||||||
// function called by ecc aspects, when an uncorrectable error is detected
|
// function called by ecc aspects, when an uncorrectable error is detected
|
||||||
BPSingleListener func_ecc_panic(ECC_FUNC_PANIC);
|
BPSingleListener func_ecc_panic(addr_panic);
|
||||||
simulator.addListener(&func_ecc_panic);
|
if (addr_panic != ADDR_INV) {
|
||||||
|
simulator.addListener(&func_ecc_panic);
|
||||||
|
}
|
||||||
|
|
||||||
#if LOCAL && 0
|
#if LOCAL && 0
|
||||||
// XXX debug
|
// XXX debug
|
||||||
@ -433,8 +447,12 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
result->set_latest_ip(simulator.getRegisterManager().getInstructionPointer());
|
result->set_latest_ip(simulator.getRegisterManager().getInstructionPointer());
|
||||||
|
|
||||||
// record error_corrected regardless of result
|
// record error_corrected regardless of result
|
||||||
int32_t error_corrected = simulator.getMemoryManager().getByte(ECC_ERROR_CORRECTED);
|
if (addr_errors_corrected != ADDR_INV) {
|
||||||
result->set_error_corrected(error_corrected);
|
int32_t error_corrected = simulator.getMemoryManager().getByte(addr_errors_corrected);
|
||||||
|
result->set_error_corrected(error_corrected);
|
||||||
|
} else {
|
||||||
|
result->set_error_corrected(0);
|
||||||
|
}
|
||||||
|
|
||||||
// record ecos_test_result
|
// record ecos_test_result
|
||||||
if ( (ecos_test_passed == true) && (ecos_test_failed == false) ) {
|
if ( (ecos_test_passed == true) && (ecos_test_failed == false) ) {
|
||||||
@ -492,24 +510,59 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
}
|
}
|
||||||
#endif // PREREQUISITES
|
#endif // PREREQUISITES
|
||||||
|
|
||||||
|
bool EcosKernelTestExperiment::readELFSymbols(
|
||||||
|
fail::guest_address_t& entry,
|
||||||
|
fail::guest_address_t& finish,
|
||||||
|
fail::guest_address_t& test_output,
|
||||||
|
fail::guest_address_t& errors_corrected,
|
||||||
|
fail::guest_address_t& panic,
|
||||||
|
fail::guest_address_t& text_start,
|
||||||
|
fail::guest_address_t& text_end)
|
||||||
|
{
|
||||||
|
ElfReader elfreader(EcosKernelTestCampaign::filename_elf(m_variant, m_benchmark).c_str());
|
||||||
|
entry = elfreader.getAddressByName("cyg_start");
|
||||||
|
finish = elfreader.getAddressByName("cyg_test_exit");
|
||||||
|
test_output = elfreader.getAddressByName("cyg_test_output");
|
||||||
|
errors_corrected = elfreader.getAddressByName("errors_corrected");
|
||||||
|
panic = elfreader.getAddressByName("_Z9ecc_panicv");
|
||||||
|
text_start = elfreader.getAddressByName("_stext");
|
||||||
|
text_end = elfreader.getAddressByName("_etext");
|
||||||
|
|
||||||
|
// it's OK if errors_corrected or ecc_panic are missing
|
||||||
|
if (entry == ADDR_INV || finish == ADDR_INV || test_output == ADDR_INV ||
|
||||||
|
text_start == ADDR_INV || text_end == ADDR_INV) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool EcosKernelTestExperiment::run()
|
bool EcosKernelTestExperiment::run()
|
||||||
{
|
{
|
||||||
log << "startup" << endl;
|
log << "startup" << endl;
|
||||||
|
|
||||||
#if PREREQUISITES
|
#if PREREQUISITES
|
||||||
|
log << "retrieving ELF symbol addresses ..." << endl;
|
||||||
|
guest_address_t entry, finish, test_output, errors_corrected,
|
||||||
|
panic, text_start, text_end;
|
||||||
|
if (!readELFSymbols(entry, finish, test_output, errors_corrected,
|
||||||
|
panic, text_start, text_end)) {
|
||||||
|
log << "failed, essential symbols are missing!" << endl;
|
||||||
|
simulator.terminate(1);
|
||||||
|
}
|
||||||
|
|
||||||
// step 0
|
// step 0
|
||||||
if(retrieveGuestAddresses()) {
|
if(retrieveGuestAddresses(finish)) {
|
||||||
log << "STEP 0 finished: rebooting ..." << endl;
|
log << "STEP 0 finished: rebooting ..." << endl;
|
||||||
simulator.reboot();
|
simulator.reboot();
|
||||||
} else { return false; }
|
} else { return false; }
|
||||||
|
|
||||||
// step 1
|
// step 1
|
||||||
if(establishState()) {
|
if(establishState(entry, errors_corrected)) {
|
||||||
log << "STEP 1 finished: proceeding ..." << endl;
|
log << "STEP 1 finished: proceeding ..." << endl;
|
||||||
} else { return false; }
|
} else { return false; }
|
||||||
|
|
||||||
// step 2
|
// step 2
|
||||||
if(performTrace()) {
|
if(performTrace(entry, finish)) {
|
||||||
log << "STEP 2 finished: terminating ..." << endl;
|
log << "STEP 2 finished: terminating ..." << endl;
|
||||||
} else { return false; }
|
} else { return false; }
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "efw/ExperimentFlow.hpp"
|
#include "efw/ExperimentFlow.hpp"
|
||||||
#include "efw/JobClient.hpp"
|
#include "efw/JobClient.hpp"
|
||||||
#include "util/Logger.hpp"
|
#include "util/Logger.hpp"
|
||||||
|
#include "sal/SALConfig.hpp"
|
||||||
|
|
||||||
class EcosKernelTestExperiment : public fail::ExperimentFlow {
|
class EcosKernelTestExperiment : public fail::ExperimentFlow {
|
||||||
fail::JobClient m_jc;
|
fail::JobClient m_jc;
|
||||||
@ -12,9 +15,17 @@ public:
|
|||||||
EcosKernelTestExperiment() : log("eCos Kernel Test", false) {}
|
EcosKernelTestExperiment() : log("eCos Kernel Test", false) {}
|
||||||
bool run();
|
bool run();
|
||||||
|
|
||||||
bool retrieveGuestAddresses(); // step 0
|
bool retrieveGuestAddresses(fail::guest_address_t addr_finish); // step 0
|
||||||
bool establishState(); // step 1
|
bool establishState(fail::guest_address_t addr_entry, fail::guest_address_t addr_errors_corrected); // step 1
|
||||||
bool performTrace(); // step 2
|
bool performTrace(fail::guest_address_t addr_entry, fail::guest_address_t addr_finish); // step 2
|
||||||
bool faultInjection(); // step 3
|
bool faultInjection(); // step 3
|
||||||
};
|
|
||||||
|
|
||||||
|
bool readELFSymbols(
|
||||||
|
fail::guest_address_t& entry,
|
||||||
|
fail::guest_address_t& finish,
|
||||||
|
fail::guest_address_t& test_output,
|
||||||
|
fail::guest_address_t& errors_corrected,
|
||||||
|
fail::guest_address_t& panic,
|
||||||
|
fail::guest_address_t& text_start,
|
||||||
|
fail::guest_address_t& text_end);
|
||||||
|
};
|
||||||
|
|||||||
@ -1,23 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// autogenerated, don't edit!
|
#define PREREQUISITES 0
|
||||||
|
|
||||||
// user-specified start-function address:
|
|
||||||
// nm -C thread1.elf|fgrep cyg_start
|
|
||||||
#define ECOS_FUNC_ENTRY 0x0000409c
|
|
||||||
// cyg_test_exit address
|
|
||||||
#define ECOS_FUNC_FINISH 0x00005f0c
|
|
||||||
// cyg_test_output address
|
|
||||||
#define ECOS_FUNC_TEST_OUTPUT 0x00005f14
|
|
||||||
// the variable that's increased if ECC corrects an error:
|
|
||||||
#define ECOS_ERROR_CORRECTED 0x99999999
|
|
||||||
|
|
||||||
// text begin:
|
|
||||||
// nm -C thread1.elf|fgrep _stext
|
|
||||||
#define ECOS_TEXT_START 0x00003000
|
|
||||||
// text end:
|
|
||||||
// nm -C thread1.elf|fgrep _etext
|
|
||||||
#define ECOS_TEXT_END 0x0001627a
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user