The patch I announced on the mailing list regarding address space recognition.
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1275 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -39,7 +39,7 @@ bool FaultCoverageExperiment::run()
|
||||
// set breakpoint at start address of the function to be analyzed ("observed");
|
||||
// wait until instruction pointer reaches that address
|
||||
cout << "[FaultCoverageExperiment] Setting up experiment. Allowing to start now." << endl;
|
||||
BPEvent ev_func_start(INST_ADDR_FUNC_START);
|
||||
BPSingleEvent ev_func_start(INST_ADDR_FUNC_START);
|
||||
simulator.addEvent(&ev_func_start);
|
||||
|
||||
cout << "[FaultCoverageExperiment] Waiting for function start address..." << endl;
|
||||
@ -72,14 +72,14 @@ bool FaultCoverageExperiment::run()
|
||||
cout << "done!" << endl;
|
||||
|
||||
// breakpoint at function exit
|
||||
BPEvent ev_func_end(INST_ADDR_FUNC_END);
|
||||
BPSingleEvent ev_func_end(INST_ADDR_FUNC_END);
|
||||
simulator.addEvent(&ev_func_end);
|
||||
|
||||
// no need to continue simulation if we want to
|
||||
// inject *now*
|
||||
if (instr > 0) {
|
||||
// breakpoint $instr instructions in the future
|
||||
BPEvent ev_instr_reached(ANY_ADDR);
|
||||
BPSingleEvent ev_instr_reached(ANY_ADDR);
|
||||
ev_instr_reached.setCounter(instr);
|
||||
simulator.addEvent(&ev_instr_reached);
|
||||
|
||||
@ -96,7 +96,7 @@ bool FaultCoverageExperiment::run()
|
||||
// catch traps and timeout
|
||||
TrapEvent ev_trap; // any traps
|
||||
simulator.addEvent(&ev_trap);
|
||||
BPEvent ev_timeout(ANY_ADDR);
|
||||
BPSingleEvent ev_timeout(ANY_ADDR);
|
||||
ev_timeout.setCounter(1000);
|
||||
simulator.addEvent(&ev_timeout);
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ bool MHTestExperiment::run()
|
||||
|
||||
cout << "[MHTestExperiment] Let's go" << endl;
|
||||
#if 0
|
||||
fi::BPEvent mainbp(0x00003c34);
|
||||
fi::BPSingleEvent mainbp(0x00003c34);
|
||||
sal::simulator.addEventAndWait(&mainbp);
|
||||
cout << "[MHTestExperiment] breakpoint reached, saving" << endl;
|
||||
sal::simulator.save("hello.main");
|
||||
@ -22,7 +22,7 @@ bool MHTestExperiment::run()
|
||||
int num = par.msg.input();
|
||||
cout << "[MHExperiment] stepping " << num << " instructions" << endl;
|
||||
if (num > 0) {
|
||||
fi::BPEvent nextbp(fi::ANY_ADDR);
|
||||
fi::BPSingleEvent nextbp(fi::ANY_ADDR);
|
||||
nextbp.setCounter(num);
|
||||
sal::simulator.addEventAndWait(&nextbp);
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ bool TracingTest::run()
|
||||
|
||||
#if 1
|
||||
// STEP 1: run until interesting function starts, and save state
|
||||
BPEvent breakpoint(0x00101658);
|
||||
BPSingleEvent breakpoint(0x00101658);
|
||||
simulator.addEventAndWait(&breakpoint);
|
||||
cout << "[TracingTest] main() reached, saving" << endl;
|
||||
|
||||
@ -40,7 +40,7 @@ bool TracingTest::run()
|
||||
simulator.addFlow(&tp);
|
||||
|
||||
cout << "[TracingTest] tracing 1000000 instructions" << endl;
|
||||
BPEvent timeout(fi::ANY_ADDR);
|
||||
BPSingleEvent timeout(fi::ANY_ADDR);
|
||||
timeout.setCounter(1000000);
|
||||
simulator.addEvent(&timeout);
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ bool DataRetrievalExperiment::run()
|
||||
cout << "[getExperimentDataExperiment] Experiment start." << endl;
|
||||
|
||||
// Breakpoint address for Memtest86:
|
||||
fi::BPEvent mainbp(MEMTEST86_BREAKPOINT);
|
||||
fi::BPSingleEvent mainbp(MEMTEST86_BREAKPOINT);
|
||||
sal::simulator.addEventAndWait(&mainbp);
|
||||
cout << "[getExperimentDataExperiment] Breakpoint reached." << endl;
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ bool ChecksumOOStuBSExperiment::run()
|
||||
{
|
||||
char const *statename = "checksum-oostubs.state";
|
||||
Logger log("Checksum-OOStuBS", false);
|
||||
fi::BPEvent bp;
|
||||
fi::BPSingleEvent bp;
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
@ -75,7 +75,7 @@ bool ChecksumOOStuBSExperiment::run()
|
||||
bp.setWatchInstructionPointer(fi::ANY_ADDR);
|
||||
bp.setCounter(OOSTUBS_NUMINSTR);
|
||||
sal::simulator.addEvent(&bp);
|
||||
fi::BPEvent func_finish(OOSTUBS_FUNC_FINISH);
|
||||
fi::BPSingleEvent func_finish(OOSTUBS_FUNC_FINISH);
|
||||
sal::simulator.addEvent(&func_finish);
|
||||
|
||||
if (sal::simulator.waitAny() == &func_finish) {
|
||||
@ -145,7 +145,7 @@ bool ChecksumOOStuBSExperiment::run()
|
||||
job.close();
|
||||
|
||||
// reaching finish() could happen before OR after FI
|
||||
fi::BPEvent func_finish(OOSTUBS_FUNC_FINISH);
|
||||
fi::BPSingleEvent func_finish(OOSTUBS_FUNC_FINISH);
|
||||
sal::simulator.addEvent(&func_finish);
|
||||
bool finish_reached = false;
|
||||
|
||||
@ -208,10 +208,10 @@ bool ChecksumOOStuBSExperiment::run()
|
||||
fi::TrapEvent ev_trap(fi::ANY_TRAP);
|
||||
sal::simulator.addEvent(&ev_trap);
|
||||
// OOStuBS' way to terminally halt (CLI+HLT)
|
||||
fi::BPEvent ev_halt(OOSTUBS_FUNC_CPU_HALT);
|
||||
fi::BPSingleEvent ev_halt(OOSTUBS_FUNC_CPU_HALT);
|
||||
sal::simulator.addEvent(&ev_halt);
|
||||
// remaining instructions until "normal" ending
|
||||
fi::BPEvent ev_done(fi::ANY_ADDR);
|
||||
fi::BPSingleEvent ev_done(fi::ANY_ADDR);
|
||||
ev_done.setCounter(OOSTUBS_NUMINSTR + OOSTUBS_RECOVERYINSTR - instr_offset);
|
||||
sal::simulator.addEvent(&ev_done);
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ using std::endl;
|
||||
bool CoolChecksumExperiment::run()
|
||||
{
|
||||
Logger log("CoolChecksum", false);
|
||||
fi::BPEvent bp;
|
||||
fi::BPSingleEvent bp;
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
@ -156,9 +156,9 @@ bool CoolChecksumExperiment::run()
|
||||
}
|
||||
|
||||
// aftermath
|
||||
fi::BPEvent ev_done(COOL_ECC_CALCDONE);
|
||||
fi::BPSingleEvent ev_done(COOL_ECC_CALCDONE);
|
||||
sal::simulator.addEvent(&ev_done);
|
||||
fi::BPEvent ev_timeout(fi::ANY_ADDR);
|
||||
fi::BPSingleEvent ev_timeout(fi::ANY_ADDR);
|
||||
ev_timeout.setCounter(COOL_ECC_NUMINSTR + 3000);
|
||||
sal::simulator.addEvent(&ev_timeout);
|
||||
fi::TrapEvent ev_trap(fi::ANY_TRAP);
|
||||
|
||||
@ -31,7 +31,7 @@ bool fireinterruptExperiment::run()
|
||||
while(1){
|
||||
int j = 0;
|
||||
for(j=0 ; j<=100 ; j++){
|
||||
fi::BPEvent mainbp(0x1045f5);
|
||||
fi::BPSingleEvent mainbp(0x1045f5);
|
||||
sal::simulator.addEventAndWait(&mainbp);
|
||||
}
|
||||
sal::simulator.fireInterrupt(1);
|
||||
|
||||
@ -24,7 +24,7 @@ bool hscsimpleExperiment::run()
|
||||
// do funny things here...
|
||||
#if 1
|
||||
// STEP 1
|
||||
fi::BPEvent mainbp(0x00003c34);
|
||||
fi::BPSingleEvent mainbp(0x00003c34);
|
||||
sal::simulator.addEventAndWait(&mainbp);
|
||||
log << "breakpoint reached, saving" << endl;
|
||||
sal::simulator.save("hello.state");
|
||||
@ -35,7 +35,7 @@ bool hscsimpleExperiment::run()
|
||||
log << "restored!" << endl;
|
||||
|
||||
log << "waiting for last square() instruction" << endl;
|
||||
fi::BPEvent breakpoint(0x3c9e); // square(x) ret instruction
|
||||
fi::BPSingleEvent breakpoint(0x3c9e); // square(x) ret instruction
|
||||
sal::simulator.addEventAndWait(&breakpoint);
|
||||
log << "injecting hellish fault" << endl;
|
||||
// RID_CAX is the RAX register in 64 bit mode and EAX in 32 bit mode:
|
||||
|
||||
31
core/experiments/l4sys/CMakeLists.txt
Normal file
31
core/experiments/l4sys/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
set(EXPERIMENT_NAME l4sys)
|
||||
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})
|
||||
74
core/experiments/l4sys/campaign.cc
Normal file
74
core/experiments/l4sys/campaign.cc
Normal file
@ -0,0 +1,74 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "campaign.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "controller/CampaignManager.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
#include "SAL/SALConfig.hpp"
|
||||
|
||||
using namespace fi;
|
||||
using std::endl;
|
||||
|
||||
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 < COOL_ECC_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);
|
||||
|
||||
fi::campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
fi::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 *>(fi::campaignmanager.getDone()))) {
|
||||
rescount++;
|
||||
|
||||
results << std::hex
|
||||
<< res->msg.injection_ip() << ","
|
||||
<< std::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;
|
||||
}
|
||||
20
core/experiments/l4sys/campaign.hpp
Normal file
20
core/experiments/l4sys/campaign.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __COOLCAMPAIGN_HPP__
|
||||
#define __COOLCAMPAIGN_HPP__
|
||||
|
||||
#include "controller/Campaign.hpp"
|
||||
#include "controller/ExperimentData.hpp"
|
||||
#include "l4sys.pb.h"
|
||||
|
||||
class L4SysExperimentData : public fi::ExperimentData {
|
||||
public:
|
||||
L4SysProtoMsg msg;
|
||||
L4SysExperimentData() : fi::ExperimentData(&msg) {}
|
||||
};
|
||||
|
||||
|
||||
class L4SysCampaign : public fi::Campaign {
|
||||
public:
|
||||
virtual bool run();
|
||||
};
|
||||
|
||||
#endif
|
||||
316
core/experiments/l4sys/experiment.cc
Normal file
316
core/experiments/l4sys/experiment.cc
Normal file
@ -0,0 +1,316 @@
|
||||
#include <iostream>
|
||||
#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 "controller/Event.hpp"
|
||||
#include "config/AspectConfig.hpp"
|
||||
|
||||
#include "l4sys.pb.h"
|
||||
|
||||
using std::endl;
|
||||
|
||||
// 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_GUESTSYS) || \
|
||||
!defined(CONFIG_EVENT_INTERRUPT)
|
||||
#error This experiment needs: breakpoints, suppressed-interrupts, traps, guest system 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";
|
||||
sal::address_t const aspace = 0x1fd44000;
|
||||
std::string output;
|
||||
std::vector<sal::address_t> instr_list;
|
||||
std::string golden_run;
|
||||
//the program needs to run 5 times without a fault
|
||||
const unsigned times_run = 5;
|
||||
|
||||
std::string L4SysExperiment::sanitised(std::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;
|
||||
}
|
||||
|
||||
fi::BaseEvent* L4SysExperiment::waitGuestOrOther(bool clear_output) {
|
||||
fi::GuestEvent ev_guest;
|
||||
fi::BaseEvent* ev = NULL;
|
||||
if (clear_output)
|
||||
output.clear();
|
||||
while (true) {
|
||||
sal::simulator.addEvent(&ev_guest);
|
||||
ev = sal::simulator.waitAny();
|
||||
sal::simulator.removeEvent(&ev_guest);
|
||||
if (ev == &ev_guest) {
|
||||
output += ev_guest.getData();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ev;
|
||||
}
|
||||
|
||||
bool L4SysExperiment::run() {
|
||||
Logger log("L4Sys", false);
|
||||
fi::BPSingleEvent bp(0, aspace);
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
//FIXME: this is a race condition:
|
||||
//only one L4SysExperiment instance should execute this block
|
||||
//at a time
|
||||
|
||||
struct stat teststruct;
|
||||
// STEP 1: run until interesting function starts, and save state
|
||||
if (stat(state_folder, &teststruct) == -1) {
|
||||
bp.setWatchInstructionPointer(COOL_ECC_FUNC_ENTRY);
|
||||
sal::simulator.addEventAndWait(&bp);
|
||||
|
||||
log << "test function entry reached, saving state" << endl;
|
||||
log << "EIP = " << std::hex << bp.getTriggerInstructionPointer()
|
||||
<< " or "
|
||||
<< sal::simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
sal::simulator.save(state_folder);
|
||||
}
|
||||
|
||||
// STEP 2: determine instructions executed
|
||||
if (stat(instr_list_fn, &teststruct) == -1) {
|
||||
log << "restoring state" << endl;
|
||||
sal::simulator.restore(state_folder);
|
||||
log << "EIP = " << std::hex
|
||||
<< sal::simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
sal::simulator.addSuppressedInterrupt(32);
|
||||
|
||||
std::ofstream instr_list_file(instr_list_fn);
|
||||
instr_list_file << std::hex;
|
||||
bp.setWatchInstructionPointer(fi::ANY_ADDR);
|
||||
while (bp.getTriggerInstructionPointer() != COOL_ECC_CALCDONE) {
|
||||
sal::simulator.addEventAndWait(&bp);
|
||||
//short sanity check
|
||||
sal::address_t curr_instr = bp.getTriggerInstructionPointer();
|
||||
assert(
|
||||
curr_instr == sal::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 {
|
||||
std::ifstream instr_list_file(instr_list_fn);
|
||||
instr_list_file >> std::hex;
|
||||
while (!instr_list_file.eof()) {
|
||||
sal::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;
|
||||
sal::simulator.restore(state_folder);
|
||||
log << "EIP = " << std::hex
|
||||
<< sal::simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
sal::simulator.addSuppressedInterrupt(32);
|
||||
|
||||
std::ofstream golden_run_file(golden_run_fn);
|
||||
bp.setWatchInstructionPointer(COOL_ECC_CALCDONE);
|
||||
bp.setCounter(times_run);
|
||||
sal::simulator.addEvent(&bp);
|
||||
fi::BaseEvent* ev = waitGuestOrOther(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();
|
||||
sal::simulator.terminate(10);
|
||||
}
|
||||
sal::simulator.clearEvents();
|
||||
bp.setCounter(1);
|
||||
log << "saving output generated during normal execution" << endl;
|
||||
golden_run_file.close();
|
||||
} else {
|
||||
std::ifstream golden_run_file(golden_run_fn);
|
||||
|
||||
//shamelessly copied from http://stackoverflow.com/questions/2602013/:
|
||||
golden_run_file.seekg(0, std::ios::end);
|
||||
size_t flen = golden_run_file.tellg();
|
||||
golden_run.reserve(flen);
|
||||
golden_run_file.seekg(0, std::ios::beg);
|
||||
|
||||
golden_run.assign((std::istreambuf_iterator<char>(golden_run_file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
golden_run_file.close();
|
||||
|
||||
//the generated output probably has a similar length
|
||||
output.reserve(flen);
|
||||
}
|
||||
|
||||
//end of critical section
|
||||
|
||||
// STEP 4: The actual experiment.
|
||||
for (int i = 0; i < COOL_ECC_NUMINSTR; i++) {
|
||||
log << "restoring state" << endl;
|
||||
sal::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
|
||||
sal::simulator.terminate(1); // "return (false);" ?
|
||||
}
|
||||
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]);
|
||||
sal::simulator.addEvent(&bp);
|
||||
//and log the output
|
||||
waitGuestOrOther(true);
|
||||
|
||||
// inject
|
||||
sal::RegisterManager& rm = sal::simulator.getRegisterManager();
|
||||
sal::Register *ebx = rm.getRegister(sal::RID_EBX);
|
||||
sal::regdata_t data = ebx->getData();
|
||||
sal::regdata_t newdata = data ^ (1 << bit_offset);
|
||||
ebx->setData(newdata);
|
||||
// note at what IP we did it
|
||||
sal::address_t injection_ip =
|
||||
sal::simulator.getRegisterManager().getInstructionPointer();
|
||||
param.msg.set_injection_ip(injection_ip);
|
||||
log << "inject @ ip " << injection_ip << " (offset " << std::dec
|
||||
<< instr_offset << ")" << " bit " << bit_offset << ": 0x"
|
||||
<< std::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]) {
|
||||
std::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());
|
||||
|
||||
sal::simulator.clearEvents();
|
||||
m_jc.sendResult(param);
|
||||
continue;
|
||||
}
|
||||
|
||||
// aftermath
|
||||
fi::BPSingleEvent ev_done(COOL_ECC_CALCDONE, aspace);
|
||||
ev_done.setCounter(times_run);
|
||||
sal::simulator.addEvent(&ev_done);
|
||||
const unsigned instr_run = times_run * COOL_ECC_NUMINSTR;
|
||||
fi::BPSingleEvent ev_timeout(fi::ANY_ADDR, aspace);
|
||||
ev_timeout.setCounter(instr_run + 3000);
|
||||
sal::simulator.addEvent(&ev_timeout);
|
||||
fi::TrapEvent ev_trap(fi::ANY_TRAP);
|
||||
sal::simulator.addEvent(&ev_trap);
|
||||
fi::InterruptEvent ev_intr(fi::ANY_INTERRUPT);
|
||||
//ten times as many interrupts as instructions justify an exception
|
||||
ev_intr.setCounter(instr_run * 10);
|
||||
sal::simulator.addEvent(&ev_intr);
|
||||
|
||||
//do not discard output recorded so far
|
||||
fi::BaseEvent *ev = waitGuestOrOther(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 << std::dec << "Result DONE" << endl;
|
||||
param.msg.set_resulttype(param.msg.CALCDONE);
|
||||
} else {
|
||||
log << std::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 << std::dec << "Result TIMEOUT" << endl;
|
||||
param.msg.set_resulttype(param.msg.TIMEOUT);
|
||||
param.msg.set_resultdata(
|
||||
sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
param.msg.set_output(sanitised(output.c_str()));
|
||||
} else if (ev == &ev_trap) {
|
||||
log << std::dec << "Result TRAP #" << ev_trap.getTriggerNumber()
|
||||
<< endl;
|
||||
param.msg.set_resulttype(param.msg.TRAP);
|
||||
param.msg.set_resultdata(
|
||||
sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
param.msg.set_output(sanitised(output.c_str()));
|
||||
} else if (ev == &ev_intr) {
|
||||
log << std::hex << "Result INT FLOOD; Last INT #:"
|
||||
<< ev_intr.getTriggerNumber() << endl;
|
||||
param.msg.set_resulttype(param.msg.INTR);
|
||||
param.msg.set_resultdata(
|
||||
sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
param.msg.set_output(sanitised(output.c_str()));
|
||||
} else {
|
||||
log << std::dec << "Result WTF?" << endl;
|
||||
param.msg.set_resulttype(param.msg.UNKNOWN);
|
||||
param.msg.set_resultdata(
|
||||
sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
param.msg.set_output(sanitised(output.c_str()));
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "eventid " << ev << " EIP "
|
||||
<< sal::simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
param.msg.set_details(ss.str());
|
||||
}
|
||||
|
||||
sal::simulator.clearEvents();
|
||||
m_jc.sendResult(param);
|
||||
}
|
||||
|
||||
#ifdef HEADLESS_EXPERIMENT
|
||||
sal::simulator.terminate(0);
|
||||
#endif
|
||||
// experiment successfully conducted
|
||||
return true;
|
||||
}
|
||||
17
core/experiments/l4sys/experiment.hpp
Normal file
17
core/experiments/l4sys/experiment.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef __COOLEXPERIMENT_HPP__
|
||||
#define __COOLEXPERIMENT_HPP__
|
||||
|
||||
#include "controller/ExperimentFlow.hpp"
|
||||
#include "jobserver/JobClient.hpp"
|
||||
|
||||
class L4SysExperiment : public fi::ExperimentFlow {
|
||||
fi::JobClient m_jc;
|
||||
public:
|
||||
L4SysExperiment() : m_jc("localhost") {}
|
||||
bool run();
|
||||
private:
|
||||
std::string sanitised(std::string in_str);
|
||||
fi::BaseEvent* waitGuestOrOther(bool clear_output);
|
||||
};
|
||||
|
||||
#endif
|
||||
11
core/experiments/l4sys/experimentInfo.hpp
Normal file
11
core/experiments/l4sys/experimentInfo.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __EXPERIMENT_INFO_HPP__
|
||||
#define __EXPERIMENT_INFO_HPP__
|
||||
|
||||
// FIXME autogenerate this
|
||||
|
||||
#define COOL_ECC_FUNC_ENTRY 0x1007cd0
|
||||
#define COOL_ECC_CALCDONE 0x1007d3a
|
||||
#define COOL_ECC_NUMINSTR 3166
|
||||
#define HEADLESS_EXPERIMENT
|
||||
|
||||
#endif
|
||||
26
core/experiments/l4sys/l4sys.proto
Normal file
26
core/experiments/l4sys/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 {
|
||||
CALCDONE = 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
core/experiments/l4sys/main.cc
Normal file
15
core/experiments/l4sys/main.cc
Normal file
@ -0,0 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "controller/CampaignManager.hpp"
|
||||
#include "experiments/l4sys/campaign.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
L4SysCampaign c;
|
||||
if (fi::campaignmanager.runCampaign(&c)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@ bool WeathermonitorExperiment::run()
|
||||
{
|
||||
char const *statename = "bochs.state";
|
||||
Logger log("Weathermonitor", false);
|
||||
fi::BPEvent bp;
|
||||
fi::BPSingleEvent bp;
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
@ -78,7 +78,7 @@ bool WeathermonitorExperiment::run()
|
||||
bp.setWatchInstructionPointer(WEATHER_FUNC_WAIT_END);
|
||||
bp.setCounter(WEATHER_NUMITER_TRACING);
|
||||
sal::simulator.addEvent(&bp);
|
||||
fi::BPEvent ev_count(fi::ANY_ADDR);
|
||||
fi::BPSingleEvent ev_count(fi::ANY_ADDR);
|
||||
sal::simulator.addEvent(&ev_count);
|
||||
|
||||
// count instructions
|
||||
@ -168,14 +168,14 @@ bool WeathermonitorExperiment::run()
|
||||
*/
|
||||
|
||||
// this marks THE END
|
||||
fi::BPEvent ev_end(fi::ANY_ADDR);
|
||||
fi::BPSingleEvent ev_end(fi::ANY_ADDR);
|
||||
ev_end.setCounter(WEATHER_NUMINSTR_TRACING + WEATHER_NUMINSTR_AFTER);
|
||||
sal::simulator.addEvent(&ev_end);
|
||||
|
||||
// count loop iterations by counting wait_begin() calls
|
||||
// FIXME would be nice to have a callback API for this as this needs to
|
||||
// be done "in parallel"
|
||||
fi::BPEvent ev_wait_begin(WEATHER_FUNC_WAIT_BEGIN);
|
||||
fi::BPSingleEvent ev_wait_begin(WEATHER_FUNC_WAIT_BEGIN);
|
||||
sal::simulator.addEvent(&ev_wait_begin);
|
||||
int count_loop_iter_before = 0;
|
||||
|
||||
@ -242,7 +242,7 @@ bool WeathermonitorExperiment::run()
|
||||
sal::simulator.addEvent(&ev_below_text);
|
||||
sal::simulator.addEvent(&ev_beyond_text);
|
||||
// error detected
|
||||
fi::BPEvent ev_detected(WEATHER_FUNC_VPTR_PANIC);
|
||||
fi::BPSingleEvent ev_detected(WEATHER_FUNC_VPTR_PANIC);
|
||||
sal::simulator.addEvent(&ev_detected);
|
||||
|
||||
#if LOCAL && 0
|
||||
|
||||
Reference in New Issue
Block a user