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/l4-sys/CMakeLists.txt
Normal file
31
src/experiments/l4-sys/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
set(EXPERIMENT_NAME l4-sys)
|
||||
set(EXPERIMENT_TYPE L4SysExperiment)
|
||||
configure_file(../instantiate-experiment.ah.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
|
||||
)
|
||||
|
||||
## Setup desired protobuf descriptions HERE ##
|
||||
set(MY_PROTOS
|
||||
l4sys.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})
|
||||
75
src/experiments/l4-sys/campaign.cc
Normal file
75
src/experiments/l4-sys/campaign.cc
Normal file
@ -0,0 +1,75 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "campaign.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "cpn/CampaignManager.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
#include "sal/SALConfig.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace fail;
|
||||
|
||||
char const * const results_csv = "l4sys.csv";
|
||||
|
||||
bool L4SysCampaign::run()
|
||||
{
|
||||
Logger log("L4SysCampaign");
|
||||
|
||||
#if 0
|
||||
ifstream test(results_csv);
|
||||
if (test.is_open()) {
|
||||
log << results_csv << " already exists" << endl;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
ofstream results(results_csv);
|
||||
if (!results.is_open()) {
|
||||
log << "failed to open " << results_csv << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
int count = 0;
|
||||
//iterate over one register
|
||||
for (int bit_offset = 0; bit_offset < 1; ++bit_offset) {
|
||||
for (int instr_offset = 0; instr_offset < L4SYS_NUMINSTR; ++instr_offset) {
|
||||
L4SysExperimentData *d = new L4SysExperimentData;
|
||||
d->msg.set_instr_offset(instr_offset);
|
||||
d->msg.set_bit_offset(bit_offset);
|
||||
d->msg.set_bit_offset(0);
|
||||
|
||||
campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
campaignmanager.noMoreParameters();
|
||||
log << "done enqueueing parameter sets (" << count << ")." << endl;
|
||||
|
||||
// collect results
|
||||
L4SysExperimentData *res;
|
||||
int rescount = 0;
|
||||
results << "injection_ip,instr_offset,injection_bit,resulttype,resultdata,output,details" << endl;
|
||||
while ((res = static_cast<L4SysExperimentData *>(campaignmanager.getDone()))) {
|
||||
rescount++;
|
||||
|
||||
results << hex
|
||||
<< res->msg.injection_ip() << ","
|
||||
<< dec << res->msg.instr_offset() << ","
|
||||
<< res->msg.bit_offset() << ","
|
||||
<< res->msg.resulttype() << ","
|
||||
<< res->msg.resultdata();
|
||||
if(res->msg.has_output())
|
||||
results << "," << res->msg.output();
|
||||
if(res->msg.has_details())
|
||||
results << "," << res->msg.details();
|
||||
results << endl;
|
||||
delete res;
|
||||
}
|
||||
|
||||
log << "done. sent " << count << " received " << rescount << endl;
|
||||
results.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
19
src/experiments/l4-sys/campaign.hpp
Normal file
19
src/experiments/l4-sys/campaign.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef __L4SYS_CAMPAIGN_HPP__
|
||||
#define __L4SYS_CAMPAIGN_HPP__
|
||||
|
||||
#include "cpn/Campaign.hpp"
|
||||
#include "comm/ExperimentData.hpp"
|
||||
#include "l4sys.pb.h"
|
||||
|
||||
class L4SysExperimentData : public fail::ExperimentData {
|
||||
public:
|
||||
L4SysProtoMsg msg;
|
||||
L4SysExperimentData() : fail::ExperimentData(&msg) {}
|
||||
};
|
||||
|
||||
class L4SysCampaign : public fail::Campaign {
|
||||
public:
|
||||
virtual bool run();
|
||||
};
|
||||
|
||||
#endif // __L4SYS_CAMPAIGN_HPP__
|
||||
319
src/experiments/l4-sys/experiment.cc
Normal file
319
src/experiments/l4-sys/experiment.cc
Normal file
@ -0,0 +1,319 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#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"
|
||||
|
||||
#include "l4sys.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) || !defined(CONFIG_EVENT_IOPORT) || \
|
||||
!defined(CONFIG_EVENT_INTERRUPT)
|
||||
#error This experiment needs: breakpoints, suppressed-interrupts, traps, I/O port and interrupt events, \
|
||||
save, and restore. Enable these in the configuration.
|
||||
#endif
|
||||
|
||||
char const * const state_folder = "l4sys.state";
|
||||
char const * const instr_list_fn = "ip.list";
|
||||
char const * const golden_run_fn = "golden.out";
|
||||
address_t const aspace = 0x01e00000;
|
||||
string output;
|
||||
vector<address_t> instr_list;
|
||||
string golden_run;
|
||||
//the program needs to run 5 times without a fault
|
||||
const unsigned times_run = 5;
|
||||
|
||||
string L4SysExperiment::sanitised(string in_str)
|
||||
{
|
||||
string result;
|
||||
result.reserve(in_str.size());
|
||||
for (string::iterator it = in_str.begin(); it != in_str.end(); it++) {
|
||||
unsigned char_value = static_cast<unsigned>(*it);
|
||||
if (char_value < 0x20 || char_value > 0x7E) {
|
||||
char str_nr[5];
|
||||
sprintf(str_nr, "\\%03o", char_value);
|
||||
result += str_nr;
|
||||
} else {
|
||||
result += *it;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
BaseEvent* L4SysExperiment::waitIOOrOther(bool clear_output)
|
||||
{
|
||||
IOPortEvent ev_ioport(0x3F8, true);
|
||||
BaseEvent* ev = NULL;
|
||||
if (clear_output)
|
||||
output.clear();
|
||||
while (true) {
|
||||
simulator.addEvent(&ev_ioport);
|
||||
ev = simulator.waitAny();
|
||||
simulator.removeEvent(&ev_ioport);
|
||||
if (ev == &ev_ioport) {
|
||||
output += ev_ioport.getData();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ev;
|
||||
}
|
||||
|
||||
bool L4SysExperiment::run()
|
||||
{
|
||||
Logger log("L4Sys", false);
|
||||
BPSingleEvent bp(0, aspace);
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
#ifdef PREPARE_EXPERIMENT
|
||||
|
||||
struct stat teststruct;
|
||||
// STEP 1: run until interesting function starts, and save state
|
||||
if (stat(state_folder, &teststruct) == -1) {
|
||||
bp.setWatchInstructionPointer(L4SYS_FUNC_ENTRY);
|
||||
simulator.addEventAndWait(&bp);
|
||||
|
||||
log << "test function entry reached, saving state" << endl;
|
||||
log << "EIP = " << hex << bp.getTriggerInstructionPointer()
|
||||
<< " or "
|
||||
<< simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
simulator.save(state_folder);
|
||||
}
|
||||
|
||||
// STEP 2: determine instructions executed
|
||||
if (stat(instr_list_fn, &teststruct) == -1) {
|
||||
log << "restoring state" << endl;
|
||||
simulator.restore(state_folder);
|
||||
log << "EIP = " << hex
|
||||
<< simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
simulator.addSuppressedInterrupt(32);
|
||||
|
||||
ofstream instr_list_file(instr_list_fn);
|
||||
instr_list_file << hex;
|
||||
bp.setWatchInstructionPointer(ANY_ADDR);
|
||||
while (bp.getTriggerInstructionPointer() != L4SYS_FUNC_EXIT) {
|
||||
simulator.addEventAndWait(&bp);
|
||||
//short sanity check
|
||||
address_t curr_instr = bp.getTriggerInstructionPointer();
|
||||
assert(
|
||||
curr_instr == simulator.getRegisterManager().getInstructionPointer());
|
||||
instr_list.push_back(curr_instr);
|
||||
instr_list_file << curr_instr << endl;
|
||||
}
|
||||
log << "saving instructions triggered during normal execution" << endl;
|
||||
instr_list_file.close();
|
||||
} else {
|
||||
ifstream instr_list_file(instr_list_fn);
|
||||
instr_list_file >> hex;
|
||||
while (!instr_list_file.eof()) {
|
||||
address_t curr_instr;
|
||||
instr_list_file >> curr_instr;
|
||||
instr_list.push_back(curr_instr);
|
||||
}
|
||||
instr_list_file.close();
|
||||
}
|
||||
|
||||
// STEP 3: determine the output of a "golden run"
|
||||
if (stat(golden_run_fn, &teststruct) == -1) {
|
||||
log << "restoring state" << endl;
|
||||
simulator.restore(state_folder);
|
||||
log << "EIP = " << hex
|
||||
<< simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
simulator.addSuppressedInterrupt(32);
|
||||
|
||||
ofstream golden_run_file(golden_run_fn);
|
||||
bp.setWatchInstructionPointer(L4SYS_FUNC_EXIT);
|
||||
bp.setCounter(times_run);
|
||||
simulator.addEvent(&bp);
|
||||
BaseEvent* ev = waitIOOrOther(true);
|
||||
if (ev == &bp) {
|
||||
golden_run.assign(output.c_str());
|
||||
golden_run_file << output.c_str();
|
||||
log << "Output successfully logged!" << endl;
|
||||
} else {
|
||||
log
|
||||
<< "Obviously, there is some trouble with the events registered - aborting simulation!"
|
||||
<< endl;
|
||||
golden_run_file.close();
|
||||
simulator.terminate(10);
|
||||
}
|
||||
simulator.clearEvents();
|
||||
bp.setCounter(1);
|
||||
log << "saving output generated during normal execution" << endl;
|
||||
golden_run_file.close();
|
||||
} else {
|
||||
ifstream golden_run_file(golden_run_fn);
|
||||
|
||||
//shamelessly copied from http://stackoverflow.com/questions/2602013/:
|
||||
golden_run_file.seekg(0, ios::end);
|
||||
size_t flen = golden_run_file.tellg();
|
||||
golden_run.reserve(flen);
|
||||
golden_run_file.seekg(0, ios::beg);
|
||||
|
||||
golden_run.assign((istreambuf_iterator<char>(golden_run_file)),
|
||||
istreambuf_iterator<char>());
|
||||
|
||||
golden_run_file.close();
|
||||
|
||||
//the generated output probably has a similar length
|
||||
output.reserve(flen);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// STEP 4: The actual experiment.
|
||||
for (int i = 0; i < 1/*L4SYS_NUMINSTR*/; i++) {
|
||||
log << "restoring state" << endl;
|
||||
simulator.restore(state_folder);
|
||||
|
||||
log << "asking job server for experiment parameters" << endl;
|
||||
L4SysExperimentData 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;
|
||||
|
||||
bp.setWatchInstructionPointer(instr_list[instr_offset]);
|
||||
simulator.addEvent(&bp);
|
||||
//and log the output
|
||||
waitIOOrOther(true);
|
||||
|
||||
// inject
|
||||
RegisterManager& rm = simulator.getRegisterManager();
|
||||
Register *ebx = rm.getRegister(RID_CBX);
|
||||
regdata_t data = ebx->getData();
|
||||
regdata_t newdata = data ^ (1 << bit_offset);
|
||||
ebx->setData(newdata);
|
||||
// note at what IP we did it
|
||||
address_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 (injection_ip != instr_list[instr_offset]) {
|
||||
stringstream ss;
|
||||
ss << "SANITY CHECK FAILED: " << injection_ip << " != "
|
||||
<< instr_list[instr_offset] << 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(L4SYS_FUNC_EXIT, aspace);
|
||||
ev_done.setCounter(times_run);
|
||||
simulator.addEvent(&ev_done);
|
||||
const unsigned instr_run = times_run * L4SYS_NUMINSTR;
|
||||
BPSingleEvent ev_timeout(ANY_ADDR, aspace);
|
||||
ev_timeout.setCounter(instr_run + 3000);
|
||||
simulator.addEvent(&ev_timeout);
|
||||
TrapEvent ev_trap(ANY_TRAP);
|
||||
simulator.addEvent(&ev_trap);
|
||||
InterruptEvent ev_intr(ANY_INTERRUPT);
|
||||
//ten times as many interrupts as instructions justify an exception
|
||||
ev_intr.setCounter(instr_run * 10);
|
||||
simulator.addEvent(&ev_intr);
|
||||
|
||||
//do not discard output recorded so far
|
||||
BaseEvent *ev = waitIOOrOther(false);
|
||||
|
||||
/* copying a string object that contains control sequences
|
||||
* unfortunately does not work with the library I am using,
|
||||
* which is why output is passed on as C string and
|
||||
* the string compare is done on C strings
|
||||
*/
|
||||
if (ev == &ev_done) {
|
||||
if (strcmp(output.c_str(), golden_run.c_str()) == 0) {
|
||||
log << dec << "Result DONE" << endl;
|
||||
param.msg.set_resulttype(param.msg.DONE);
|
||||
} else {
|
||||
log << dec << "Result WRONG" << endl;
|
||||
param.msg.set_resulttype(param.msg.WRONG);
|
||||
param.msg.set_output(sanitised(output.c_str()));
|
||||
}
|
||||
} else if (ev == &ev_timeout) {
|
||||
log << dec << "Result TIMEOUT" << endl;
|
||||
param.msg.set_resulttype(param.msg.TIMEOUT);
|
||||
param.msg.set_resultdata(
|
||||
simulator.getRegisterManager().getInstructionPointer());
|
||||
param.msg.set_output(sanitised(output.c_str()));
|
||||
} 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());
|
||||
param.msg.set_output(sanitised(output.c_str()));
|
||||
} else if (ev == &ev_intr) {
|
||||
log << hex << "Result INT FLOOD; Last INT #:"
|
||||
<< ev_intr.getTriggerNumber() << endl;
|
||||
param.msg.set_resulttype(param.msg.INTR);
|
||||
param.msg.set_resultdata(
|
||||
simulator.getRegisterManager().getInstructionPointer());
|
||||
param.msg.set_output(sanitised(output.c_str()));
|
||||
} else {
|
||||
log << dec << "Result WTF?" << endl;
|
||||
param.msg.set_resulttype(param.msg.UNKNOWN);
|
||||
param.msg.set_resultdata(
|
||||
simulator.getRegisterManager().getInstructionPointer());
|
||||
param.msg.set_output(sanitised(output.c_str()));
|
||||
|
||||
stringstream ss;
|
||||
ss << "eventid " << ev << " EIP "
|
||||
<< simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
param.msg.set_details(ss.str());
|
||||
}
|
||||
|
||||
simulator.clearEvents();
|
||||
m_jc.sendResult(param);
|
||||
}
|
||||
|
||||
#ifdef HEADLESS_EXPERIMENT
|
||||
simulator.terminate(0);
|
||||
#endif
|
||||
// experiment successfully conducted
|
||||
return true;
|
||||
}
|
||||
23
src/experiments/l4-sys/experiment.hpp
Normal file
23
src/experiments/l4-sys/experiment.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __L4SYS_EXPERIMENT_HPP__
|
||||
#define __L4SYS_EXPERIMENT_HPP__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "efw/ExperimentFlow.hpp"
|
||||
#include "efw/JobClient.hpp"
|
||||
|
||||
class L4SysExperiment : public fail::ExperimentFlow {
|
||||
fail::JobClient m_jc;
|
||||
public:
|
||||
L4SysExperiment() : m_jc("localhost") {}
|
||||
bool run();
|
||||
private:
|
||||
// NOTE: It's good practise to use "const std::string&" as parameter type.
|
||||
// Additionaly, if you don't need the return value to be copied,
|
||||
// return a (const) reference to a class member or a static string-
|
||||
// object.
|
||||
std::string sanitised(std::string in_str);
|
||||
fail::BaseEvent* waitIOOrOther(bool clear_output);
|
||||
};
|
||||
|
||||
#endif // __L4SYS_EXPERIMENT_HPP__
|
||||
12
src/experiments/l4-sys/experimentInfo.hpp
Normal file
12
src/experiments/l4-sys/experimentInfo.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef __EXPERIMENT_INFO_HPP__
|
||||
#define __EXPERIMENT_INFO_HPP__
|
||||
|
||||
// FIXME autogenerate this
|
||||
|
||||
#define L4SYS_FUNC_ENTRY 0x1007cd0
|
||||
#define L4SYS_FUNC_EXIT 0x1007d3a
|
||||
#define L4SYS_NUMINSTR 3184
|
||||
//#define HEADLESS_EXPERIMENT
|
||||
#define PREPARE_EXPERIMENT
|
||||
|
||||
#endif // __EXPERIMENT_INFO_HPP__
|
||||
26
src/experiments/l4-sys/l4sys.proto
Normal file
26
src/experiments/l4-sys/l4sys.proto
Normal file
@ -0,0 +1,26 @@
|
||||
message L4SysProtoMsg {
|
||||
// parameters
|
||||
required int32 instr_offset = 1;
|
||||
required int32 bit_offset = 2;
|
||||
|
||||
// results
|
||||
// make these optional to reduce overhead for server->client communication
|
||||
enum ResultType {
|
||||
DONE = 1;
|
||||
TIMEOUT = 2;
|
||||
TRAP = 3;
|
||||
INTR = 4;
|
||||
WRONG = 5;
|
||||
UNKNOWN = 6;
|
||||
}
|
||||
// instruction pointer where injection was done
|
||||
optional uint32 injection_ip = 3;
|
||||
// result type, see above
|
||||
optional ResultType resulttype = 4;
|
||||
// result data, depending on resulttype (see source code)
|
||||
optional uint32 resultdata = 5;
|
||||
// generated output
|
||||
optional string output = 6;
|
||||
// optional textual description of what happened
|
||||
optional string details = 7;
|
||||
}
|
||||
15
src/experiments/l4-sys/main.cc
Normal file
15
src/experiments/l4-sys/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)
|
||||
{
|
||||
L4SysCampaign c;
|
||||
if (fail::campaignmanager.runCampaign(&c)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user