lra-simple-panda: Experiment updated for evaluation

Change-Id: I7905bda6aab7825c28b750683f2712161add325b
This commit is contained in:
Lars Rademacher
2013-12-31 15:59:16 +01:00
parent 286a28e7ae
commit 99bc6e7c03
5 changed files with 243 additions and 72 deletions

View File

@ -1,5 +1,5 @@
#ifndef __DCIAOCAMPAIGN_HPP__ #ifndef __LRA_CAMPAIGN_HPP__
#define __DCIAOCAMPAIGN_HPP__ #define __LRA_CAMPAIGN_HPP__
#include "cpn/DatabaseCampaign.hpp" #include "cpn/DatabaseCampaign.hpp"
#include "comm/ExperimentData.hpp" #include "comm/ExperimentData.hpp"
@ -18,6 +18,9 @@ class LraSimpleCampaign : public fail::DatabaseCampaign {
{ return google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName("LraSimpleProtoMsg"); } { return google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName("LraSimpleProtoMsg"); }
virtual void cb_send_pilot(DatabaseCampaignMessage pilot); virtual void cb_send_pilot(DatabaseCampaignMessage pilot);
virtual int expected_number_of_results(std::string variant, std::string benchmark) {
return 1;
}
}; };
#endif // __KESOREFCAMPAIGN_HPP__ #endif // __LRA_CAMPAIGN_HPP__

View File

@ -10,19 +10,21 @@
#include "util/WallclockTimer.hpp" #include "util/WallclockTimer.hpp"
#include "util/gzstream/gzstream.h" #include "util/gzstream/gzstream.h"
#include "util/WallclockTimer.hpp"
#include "efw/JobClient.hpp" #include "efw/JobClient.hpp"
#include "lra_simple.pb.h" #include "lra_simple.pb.h"
#include "campaign.hpp" #include "campaign.hpp"
#include "cpn/InjectionPoint.hpp"
#include "config/FailConfig.hpp" #include "config/FailConfig.hpp"
#include <fstream> #include <fstream>
#include <unistd.h> #include <unistd.h>
#include <math.h>
// 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,10 +38,26 @@ using namespace fail;
#define PREPARATION 0 #define PREPARATION 0
int32_t correct_result[100] = {
0, 6, 5, 1, 6, 2, 7, 3,
8, 4, 1, 6, 5, 9, 5, 3,
0, 6, 5, 3, 7, 1, 7, 2,
8, 3, 9, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};
// ToDo: Move this functionality to SimulatorController // ToDo: Move this functionality to SimulatorController
void LRASimplePandaExperiment::navigateToInjectionPoint(ConcreteInjectionPoint &ip) { bool LRASimplePandaExperiment::navigateToInjectionPoint(ConcreteInjectionPoint &ip) {
Logger log_nav("navigator"); Logger log_nav("navigator", false);
#ifdef CONFIG_INJECTIONPOINT_HOPS #ifdef CONFIG_INJECTIONPOINT_HOPS
// Hop nav // Hop nav
@ -60,6 +78,10 @@ void LRASimplePandaExperiment::navigateToInjectionPoint(ConcreteInjectionPoint &
InjectionPointMessage_Hops h = ipm.hops(i); InjectionPointMessage_Hops h = ipm.hops(i);
BaseListener *hop, *ev; BaseListener *hop, *ev;
// Nav-fail-bp
BPSingleListener ev_func_end(elfReader->getSymbol("main").getEnd() - 4 - LRASP_MAIN_ENDOFFSET);
simulator.addListener(&ev_func_end);
if (h.accesstype() == h.EXECUTE) { if (h.accesstype() == h.EXECUTE) {
log_nav << "BP at " << hex << h.address() << dec << endl; log_nav << "BP at " << hex << h.address() << dec << endl;
BPSingleListener bp (h.address()); BPSingleListener bp (h.address());
@ -76,56 +98,69 @@ void LRASimplePandaExperiment::navigateToInjectionPoint(ConcreteInjectionPoint &
log_nav << "Halted" << endl; log_nav << "Halted" << endl;
if (ev == &ev_func_end) {
log_nav << "Navigational error..." << endl;
simulator.clearListeners();
return false;
} else {
simulator.removeListener(&ev_func_end);
}
if (ev != hop) { if (ev != hop) {
log_nav << "FATAL ERROR: Unexpected event while navigating!" << endl; log_nav << "FATAL ERROR: Unexpected event while navigating!" << endl;
simulator.terminate(1); simulator.terminate(1);
} }
} }
#else #else
// Step nav // Step nav
InjectionPointMessage ipm; InjectionPointMessage ipm;
ip.copyInjectionPointMessage(ipm); ip.copyInjectionPointMessage(ipm);
log_nav << ipm.injection_instr() << endl; log_nav << "Navigating to instruction " << ipm.injection_instr() << endl;
BPSingleListener step(ANY_ADDR);
step.setCounter(ipm.injection_instr());
simulator.addListenerAndResume(&step);
#endif #endif
return true;
} }
bool LRASimplePandaExperiment::run() bool LRASimplePandaExperiment::run()
{ {
Logger _log("lra-simpla-panda", false); Logger logger("lra-simpla-panda", false);
_log << "Startup" << endl; logger << "Startup" << endl;
fail::ElfReader elfReader;
fail::JobClient jobClient;
elfReader = new ElfReader();
fail::JobClient *jobClient = new JobClient();
#if PREPARATION == 1 #if PREPARATION == 1
_log << "Preparation mode" << endl; logger << "Preparation mode" << endl;
// STEP 1: run until main starts, save state, record trace // STEP 1: run until main starts, save state, record trace
// TODO: store golden run output BPSingleListener func_begin(elfReader->getSymbol("main").getStart());
BPSingleListener func_begin(elfReader.getSymbol("test_code_due").getAddress());
simulator.addListenerAndResume(&func_begin); simulator.addListenerAndResume(&func_begin);
_log << "test_func() reached, beginning trace recording" << endl; logger << "test_func() reached, beginning trace recording" << endl;
TracingPlugin tp; TracingPlugin tp;
// ogzstream of(LRASP_TRACE); ogzstream of(LRASP_TRACE);
ofstream of(LRASP_TRACE);
if (of.bad()) { if (of.bad()) {
_log << "FATAL ERROR: Trace file could not be opened." << endl; logger << "FATAL ERROR: Trace file could not be opened." << endl;
simulator.terminate(); simulator.terminate();
return false; return false;
} }
tp.setTraceFile(&of); tp.setOstream(&of);
//tp.setOstream(&of);
// this must be done *after* configuring the plugin: // this must be done *after* configuring the plugin:
simulator.addFlow(&tp); simulator.addFlow(&tp);
BPSingleListener func_end(elfReader.getSymbol("test_code_due").getAddress() + elfReader.getSymbol("test_code_due").getSize() - 4); BPSingleListener func_end(elfReader->getSymbol("main").getEnd() - 4 - 28);
simulator.addListener(&func_end); simulator.addListener(&func_end);
BPSingleListener step(ANY_ADDR); BPSingleListener step(ANY_ADDR);
WallclockTimer timer;
timer.startTimer();
// count instructions // count instructions
long counter = 0; long counter = 0;
while (true) { while (true) {
@ -135,80 +170,207 @@ bool LRASimplePandaExperiment::run()
} }
counter++; counter++;
if ((counter % 1000) == 0) { if ((counter % 1000) == 0) {
_log << "Traced " << counter << " insturctions" << endl; timer.stopTimer();
of.flush(); logger << "Traced " << counter << " insturctions in " << timer << " seconds" << endl;
timer.reset();
timer.startTimer();
} }
} }
_log << "golden run took " << dec << counter << " instructions" << endl; logger << "Traced " << counter << " insturctions in " << timer << " seconds" << endl << endl;
logger << "golden run took " << dec << counter << " instructions" << endl;
simulator.removeFlow(&tp); simulator.removeFlow(&tp);
of.flush();
// serialize trace to file // serialize trace to file
if (of.fail()) { if (of.fail()) {
_log << "failed to write to trace file"<< std::endl; logger << "failed to write to trace file"<< std::endl;
return false; return false;
} }
of.close(); of.close();
#else #else // PREPARATION
unsigned executed_jobs = 0; unsigned executed_jobs = 0;
_log << "Startup!" << endl; while (true) {
logger << "asking jobserver for parameters. Undone: "<<jobClient->getNumberOfUndoneJobs() << endl;
// std::ofstream exp_output ("exp.txt");
ConcreteCPU cpu = simulator.getCPU(0);
ConcreteCPU::iterator it = cpu.begin();
it++; it++;
while (jobClient.getNumberOfUndoneJobs() > 0 || executed_jobs < 500) {
_log << "asking jobserver for parameters" << endl;
LraSimpleExperimentData param; LraSimpleExperimentData param;
if(!jobClient.getParam(param)){ if(!jobClient->getParam(param)){
_log << "Dying." << endl; // We were told to die. logger << "Dying." << endl; // We were told to die.
simulator.terminate(1); simulator.terminate(1);
} }
logger << "New param" << param.msg.DebugString() << endl;
// Get input data from Jobserver // Get input data from Jobserver
unsigned injection_instr = param.msg.fsppilot().injection_instr(); unsigned injection_instr = param.msg.fsppilot().injection_instr();
address_t data_address = param.msg.fsppilot().data_address(); address_t data_address = param.msg.fsppilot().data_address();
unsigned data_width = param.msg.fsppilot().data_width(); // unsigned data_width = param.msg.fsppilot().data_width();
ConcreteInjectionPoint ip; ConcreteInjectionPoint ip;
ip.parseFromCampaignMessage(param.msg.fsppilot()); ip.parseFromCampaignMessage(param.msg.fsppilot());
// ToDo: Insert into all 8 Bits for (unsigned experiment_id = 0; experiment_id < LRASP_NUM_EXP_PER_PILOT; ++experiment_id) {
for (int experiment_id = 0; experiment_id < 1; ++experiment_id) { LraSimpleProtoMsg_Result *result = param.msg.add_result();
LraSimpleProtoMsg_Result *result = 0; executed_jobs ++;
_log << "rebooting device" << endl; WallclockTimer timer;
timer.startTimer();
/********************
* INITIALIZATION *
********************/
logger << "rebooting device" << endl;
// Restore to the image, which starts at address(main) // Restore to the image, which starts at address(main)
simulator.reboot(); simulator.reboot();
executed_jobs ++;
// Fast forward to injection address // In this case, no entry navigation is needed
_log << "Trying to inject @ instr #" << dec << injection_instr << endl; // Otherwise we will have to navigate to the pre entry instruction!!!
BPSingleListener func_begin(elfReader->getSymbol("main").getStart());
simulator.addListenerAndResume(&func_begin);
navigateToInjectionPoint(ip); timer.stopTimer();
result->set_time_init(float(timer));
timer.reset();
uint32_t iteration_counter; /****************
simulator.getMemoryManager().getBytes(elfReader.getSymbol("test_code_idx").getAddress(), 4, (void*)(&iteration_counter)); * NAVIGATION *
****************/
logger << "Fastforwarding to instr #" << injection_instr << endl;
result = param.msg.add_result(); timer.startTimer();
if (!navigateToInjectionPoint(ip)) {
continue;
}
timer.stopTimer();
result->set_time_nav(float(timer));
timer.reset();
/***************
* INJECTION *
***************/
// We do a 8-bit flip burst
// Alternatively for single-bit-flips:
// data ^= 1 << experiment_id;
logger << "Injection bitflips at address " << hex << data_address << dec << endl;
timer.startTimer();
byte_t data = simulator.getMemoryManager().getByte(data_address);
data = ~data;
simulator.getMemoryManager().setByte(data_address, data); // write back data to register
timer.stopTimer();
result->set_time_inject(float(timer));
timer.reset();
/***************
* AFTERMATH *
***************/
logger << "Aftermath: Checking for wrong mem access, traps, timeout, wrong result or success" << endl;
timer.startTimer();
// Setup MMU
/*
* As the false positive rate is very high, if we watch a
* page with actively used memory and because of the high
* costs for a false positive (in the magnitude of seconds),
* we don't want to watch those areas.
*
* We must not watch the following areas:
* - UART I/O Port at 0x48020014 => don't watch page 0x48020000
* - .text-, .bss- and .data-segment at 0x83000000 to 0x83411000 (exclusive)
* - Stack at 0xBFD00000 to 0xC0000000
*/
MemAccessListener ev_unauth_mem_acc_1(0x0);
ev_unauth_mem_acc_1.setWatchWidth(0x48020000);
simulator.addListener(&ev_unauth_mem_acc_1);
MemAccessListener ev_unauth_mem_acc_2(0x48021000);
ev_unauth_mem_acc_2.setWatchWidth(0x83000000 - 0x48021000);
simulator.addListener(&ev_unauth_mem_acc_2);
MemAccessListener ev_unauth_mem_acc_3(0x83411000);
ev_unauth_mem_acc_3.setWatchWidth(0xBFD00000 - 0x83411000);
simulator.addListener(&ev_unauth_mem_acc_3);
MemAccessListener ev_unauth_mem_acc_4(0xC0000000);
ev_unauth_mem_acc_4.setWatchWidth(0xFFFFFFFF - 0xC0000000);
simulator.addListener(&ev_unauth_mem_acc_4);
// Traps
TrapListener ev_trap(fail::ANY_TRAP, NULL);
simulator.addListener(&ev_trap);
// Timeout
TimerListener ev_timeout(LRASP_TIMEOUT);
simulator.addListener(&ev_timeout);
// Termination
BPSingleListener ev_func_end(elfReader->getSymbol("main").getEnd() - 4 - LRASP_MAIN_ENDOFFSET);
simulator.addListener(&ev_func_end);
logger << "waiting for function exit, trap or timeout(1 second)" << endl;
BaseListener* ev = simulator.resume();
if (ev == &ev_timeout) {
logger << "Timeout!" << endl;
result->set_resulttype(result->ERR_TIMEOUT);
} else if (ev == &ev_trap) {
logger << "Trap!" << endl;
result->set_resulttype(result->ERR_TRAP);
} else if (ev == &ev_unauth_mem_acc_1 ||
ev == &ev_unauth_mem_acc_2 ||
ev == &ev_unauth_mem_acc_3 ||
ev == &ev_unauth_mem_acc_4) {
result->set_resulttype(result->ERR_OUTSIDE_TEXT);
logger << hex << "Unauthorized memory access (" << ((((MemAccessListener*)ev)->getTriggerAccessType() == fail::MemAccessEvent::MEM_READ) ? "R" : "W") <<
") at instruction " << ((MemAccessListener*)ev)->getTriggerInstructionPointer() << " access address: " <<
((MemAccessListener*)ev)->getTriggerAddress() << dec << endl;
} else if (ev == &ev_func_end) {
logger << "Function terminated!" << endl;
int32_t results[elfReader->getSymbol("result").getSize()/sizeof(int32_t)];
simulator.getMemoryManager().getBytes(elfReader->getSymbol("result").getAddress(),
elfReader->getSymbol("result").getSize(),
(unsigned char*)results);
result->set_resulttype(result->OK);
for (unsigned i = 0; i < sizeof(results) / sizeof(*results); ++i) {
if (correct_result[i] != results[i]) {
result->set_resulttype(result->ERR_WRONG_RESULT);
break;
}
}
}
timer.stopTimer();
result->set_time_aftermath(float(timer));
result->set_bitoffset(experiment_id);
result->set_loop_iteration(iteration_counter);
result->set_resulttype(result->OK);
result->set_experiment_number(executed_jobs); result->set_experiment_number(executed_jobs);
simulator.clearListeners(); simulator.clearListeners();
} }
jobClient.sendResult(param); jobClient->sendResult(param);
logger << param.debugString();
} }
_log << "jobClient.getNumberOfUndoneJobs() = " << jobClient.getNumberOfUndoneJobs() << "executed_jobs = " << executed_jobs << endl; logger << "jobClient.getNumberOfUndoneJobs() = " << jobClient->getNumberOfUndoneJobs() << "executed_jobs = " << executed_jobs << endl;
#endif // PREPARATION #endif // PREPARATION
delete elfReader;
delete jobClient;
simulator.terminate(); simulator.terminate();
return true; return true;
} }

View File

@ -3,14 +3,17 @@
#include "efw/ExperimentFlow.hpp" #include "efw/ExperimentFlow.hpp"
#include "cpn/InjectionPoint.hpp" #include "cpn/InjectionPoint.hpp"
#include "util/ElfReader.hpp"
using namespace fail; using namespace fail;
class LRASimplePandaExperiment : public ExperimentFlow { class LRASimplePandaExperiment : public ExperimentFlow {
private:
fail::ElfReader *elfReader;
public: public:
LRASimplePandaExperiment() : ExperimentFlow() {} LRASimplePandaExperiment() : ExperimentFlow() {}
bool run(); bool run();
void navigateToInjectionPoint(ConcreteInjectionPoint &ip); bool navigateToInjectionPoint(ConcreteInjectionPoint &ip);
// void navigateToInjectionPoint(ConcreteInjectionPoint &ip, std::ostream &log); // void navigateToInjectionPoint(ConcreteInjectionPoint &ip, std::ostream &log);
}; };

View File

@ -2,12 +2,10 @@
#define __LRA_SIMPLE_PANDA_EXPERIMENT_INFO_HPP__ #define __LRA_SIMPLE_PANDA_EXPERIMENT_INFO_HPP__
#define LRASP_TRACE "trace.tc" #define LRASP_TRACE "trace.tc"
#define LRASP_BIN_OFFSET 0x100000 #define LRASP_TIMEOUT 3000000 // 1500ms
#define LRASP_RESULTS "LRASP.csv" #define LRASP_RESULT_ADDRESS 0x834106b0
#define LRASP_TIMEOUT 1000000 // 1s #define LRASP_RESULTS_BYTES 1000
#define LRASP_ADDR_FUNC_BEGIN 0x83000978 #define LRASP_MAIN_ENDOFFSET 28
#define LRASP_ADDR_FUNC_END 0x83000a68 #define LRASP_NUM_EXP_PER_PILOT 1
#define LRASP_RESULT_ADDRESS 0x83016804
#define LRASP_RESULTS_BYTES 4
#endif #endif

View File

@ -7,19 +7,24 @@ message LraSimpleProtoMsg {
enum ResultType { enum ResultType {
OK = 1; OK = 1;
ERR_WRONG_RESULT = 4; ERR_WRONG_RESULT = 2;
ERR_TRAP = 5; ERR_TRAP = 3;
ERR_TIMEOUT = 6; ERR_TIMEOUT = 4;
ERR_OUTSIDE_TEXT = 7; ERR_OUTSIDE_TEXT = 5;
ERR_OUTSIDE_DATA = 8;
} }
required int32 bitoffset = 1 [(sql_primary_key) = true]; //required int32 bitoffset = 1 [(sql_primary_key) = true];
required uint32 experiment_number = 1 [(sql_primary_key) = true];
required ResultType resulttype = 2; required ResultType resulttype = 2;
required uint32 experiment_number = 3;
required uint32 loop_iteration = 4;
// Times for evaluation
required float time_init = 3;
required float time_nav = 4;
required float time_inject = 5;
required float time_aftermath = 6;
} }
} }