GenericTracing/-Experiment: add SDC detection

This change adds detection of SDCs to GenericTracing and
GenericExperiment via Bochs's I/O port E9.

Change-Id: Ie036aa97468b45cad94b6c8f73d1ef2d227547b2
This commit is contained in:
Michael Lenz
2016-02-10 12:15:01 +01:00
committed by Horst Schirmeier
parent ad558abeb6
commit d46b81eb3d
5 changed files with 85 additions and 2 deletions

View File

@ -42,6 +42,23 @@ google::protobuf::Message* GenericExperiment::cb_new_result(ExperimentData* data
return result; return result;
} }
std::vector<char> loadFile(std::string filename)
{
std::vector<char> data;
FILE *f = fopen(filename.c_str(), "rb");
if (!f) {
return data;
}
fseek(f, 0, SEEK_END);
long len = ftell(f);
fseek(f, 0, SEEK_SET);
if (len > 0) {
data.resize(len);
fread(&data[0], len, 1, f);
}
fclose(f);
return data;
}
void handleEvent(GenericExperimentMessage_Result& result, void handleEvent(GenericExperimentMessage_Result& result,
GenericExperimentMessage_Result_ResultType restype, GenericExperimentMessage_Result_ResultType restype,
@ -95,6 +112,9 @@ bool GenericExperiment::cb_start_experiment() {
CommandLine::option_handle TIMEOUT = cmd.addOption("", "timeout", Arg::Required, CommandLine::option_handle TIMEOUT = cmd.addOption("", "timeout", Arg::Required,
"--timeout \t Experiment Timeout in uS"); "--timeout \t Experiment Timeout in uS");
CommandLine::option_handle E9_FILE = cmd.addOption("", "e9-file", Arg::Required,
"--e9-file FILE \t data logged via port 0xE9 in golden run");
std::map<std::string, CommandLine::option_handle> option_handles; std::map<std::string, CommandLine::option_handle> option_handles;
for (std::map<std::string, ListenerSet *>::iterator it = end_marker_groups.begin(); for (std::map<std::string, ListenerSet *>::iterator it = end_marker_groups.begin();
@ -152,6 +172,12 @@ bool GenericExperiment::cb_start_experiment() {
} }
} }
if (cmd[E9_FILE]) {
m_log << "enabled logging on port E9 for SDC-detection" << std::endl;
enabled_e9_sol = true;
e9_file = std::string(cmd[E9_FILE].first()->arg);
}
if (cmd[WRITE_MEM_TEXT]) { if (cmd[WRITE_MEM_TEXT]) {
m_log << "Catch writes to text segment from " << hex << minimal_ip << " to " << maximal_ip << std::endl; m_log << "Catch writes to text segment from " << hex << minimal_ip << " to " << maximal_ip << std::endl;
enabled_mem_text = true; enabled_mem_text = true;
@ -229,6 +255,10 @@ bool GenericExperiment::cb_before_resume() {
simulator.addListener(*it); simulator.addListener(*it);
} }
if (enabled_e9_sol) {
simulator.addFlow(&e9_sol);
}
return true; // everything OK return true; // everything OK
} }
@ -238,7 +268,6 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) {
// Record the crash time // Record the crash time
result->set_crash_time(simulator.getTimerTicks()); result->set_crash_time(simulator.getTimerTicks());
if (event == &l_timeout) { if (event == &l_timeout) {
handleEvent(*result, result->TIMEOUT, m_Timeout); handleEvent(*result, result->TIMEOUT, m_Timeout);
} else if (event == &l_trap) { } else if (event == &l_trap) {
@ -258,6 +287,17 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) {
const ElfSymbol *symbol = listener_to_symbol[event]; const ElfSymbol *symbol = listener_to_symbol[event];
handleEvent(*result, result->OK_MARKER, symbol->getAddress()); handleEvent(*result, result->OK_MARKER, symbol->getAddress());
// check experiment's data for SDC
if (enabled_e9_sol) {
// compare golden run to experiment
std::vector<char> e9_goldenrun = loadFile(e9_file);
std::string e9_experiment = e9_sol.getOutput();
if ( ! (e9_experiment.size() == e9_goldenrun.size()
&& equal(e9_experiment.begin(), e9_experiment.end(), e9_goldenrun.begin())) ) {
handleEvent(*result, result->SDC, 0);
}
}
} else if (FAIL_marker.find(event) != FAIL_marker.end()) { } else if (FAIL_marker.find(event) != FAIL_marker.end()) {
const ElfSymbol *symbol = listener_to_symbol[event]; const ElfSymbol *symbol = listener_to_symbol[event];
handleEvent(*result, result->FAIL_MARKER, symbol->getAddress()); handleEvent(*result, result->FAIL_MARKER, symbol->getAddress());
@ -285,4 +325,10 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) {
} else { } else {
handleEvent(*result, result->UNKNOWN, 0); handleEvent(*result, result->UNKNOWN, 0);
} }
// remove and reset 0xE9 logger even if this run was not "OK"
if (enabled_e9_sol) {
simulator.removeFlow(&e9_sol);
e9_sol.resetOutput();
}
} }

View File

@ -7,6 +7,7 @@
#include "efw/JobClient.hpp" #include "efw/JobClient.hpp"
#include "util/Logger.hpp" #include "util/Logger.hpp"
#include "util/ElfReader.hpp" #include "util/ElfReader.hpp"
#include "../plugins/serialoutput/SerialOutputLogger.hpp"
#include <string> #include <string>
#include <stdlib.h> #include <stdlib.h>
#include <map> #include <map>
@ -19,6 +20,10 @@ class GenericExperiment : public fail::DatabaseExperiment {
std::string m_state_dir; std::string m_state_dir;
bool enabled_e9_sol;
std::string e9_file;
SerialOutputLogger e9_sol;
bool enabled_mem_text; bool enabled_mem_text;
fail::MemAccessListener l_mem_text; fail::MemAccessListener l_mem_text;
@ -52,6 +57,7 @@ class GenericExperiment : public fail::DatabaseExperiment {
public: public:
GenericExperiment() : DatabaseExperiment("GenericExperiment"), GenericExperiment() : DatabaseExperiment("GenericExperiment"),
m_state_dir("state"), m_state_dir("state"),
e9_sol(0xE9),
l_trap(fail::ANY_TRAP), l_timeout(0) { l_trap(fail::ANY_TRAP), l_timeout(0) {
enabled_mem_text = false; enabled_mem_text = false;
enabled_mem_outerspace = false; enabled_mem_outerspace = false;

View File

@ -13,7 +13,7 @@ message GenericExperimentMessage {
OK_MARKER = 1; OK_MARKER = 1;
FAIL_MARKER = 2; FAIL_MARKER = 2;
DETECTED_MARKER = 3; DETECTED_MARKER = 3;
GROUP1_MARKER = 4; GROUP1_MARKER = 4;
GROUP2_MARKER = 5; GROUP2_MARKER = 5;
GROUP3_MARKER = 6; GROUP3_MARKER = 6;
@ -24,6 +24,8 @@ message GenericExperimentMessage {
WRITE_TEXTSEGMENT = 10; WRITE_TEXTSEGMENT = 10;
WRITE_OUTERSPACE = 11; WRITE_OUTERSPACE = 11;
SDC = 12;
UNKNOWN = 100; UNKNOWN = 100;
} }
// result type, see above // result type, see above

View File

@ -67,6 +67,8 @@ void GenericTracing::parseOptions() {
"--serial-port \tListen to a given I/O address (default: 0x3F8)"); "--serial-port \tListen to a given I/O address (default: 0x3F8)");
CommandLine::option_handle SERIAL_FILE = cmd.addOption("", "serial-file", Arg::Required, CommandLine::option_handle SERIAL_FILE = cmd.addOption("", "serial-file", Arg::Required,
"--serial-file \tSave the serial output to file"); "--serial-file \tSave the serial output to file");
CommandLine::option_handle E9_FILE = cmd.addOption("", "e9-file", Arg::Required,
"--e9-file FILE \tData logged via port 0xE9 is stored in this file");
if (!cmd.parse()) { if (!cmd.parse()) {
cerr << "Error parsing arguments." << endl; cerr << "Error parsing arguments." << endl;
@ -228,6 +230,14 @@ void GenericTracing::parseOptions() {
serial_file = ""; serial_file = "";
} }
if (cmd[E9_FILE]) {
e9_file = std::string(cmd[E9_FILE].first()->arg);
m_log << "port E9 output is written to: " << e9_file << std::endl;
} else {
e9_file = "";
}
if (m_elf != NULL) { if (m_elf != NULL) {
m_log << "start/save symbol: " << start_symbol << " 0x" << std::hex << start_address << std::endl; m_log << "start/save symbol: " << start_symbol << " 0x" << std::hex << start_address << std::endl;
m_log << "stop symbol: " << stop_symbol << " 0x" << std::hex << stop_address << std::endl; m_log << "stop symbol: " << stop_symbol << " 0x" << std::hex << stop_address << std::endl;
@ -287,6 +297,12 @@ bool GenericTracing::run()
simulator.addFlow(&sol); simulator.addFlow(&sol);
} }
SerialOutputLogger e9_sol(0xE9);
if (e9_file != "") {
simulator.addFlow(&e9_sol);
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Step 2: Continue to the stop point // Step 2: Continue to the stop point
simulator.addListener(&l_stop_symbol); simulator.addListener(&l_stop_symbol);
@ -314,6 +330,17 @@ bool GenericTracing::run()
of_serial.close(); of_serial.close();
} }
if (e9_file != "") {
simulator.removeFlow(&e9_sol);
ofstream of_e9(e9_file.c_str(), ios::out|ios::binary);
if (!of_e9.fail()) {
of_e9 << e9_sol.getOutput();
} else {
m_log << "failed to write " << e9_file << endl;
}
of_e9.close();
}
simulator.clearListeners(); simulator.clearListeners();
simulator.terminate(); simulator.terminate();

View File

@ -28,6 +28,8 @@ class GenericTracing : public fail::ExperimentFlow {
fail::guest_address_t serial_port; fail::guest_address_t serial_port;
std::string serial_file; std::string serial_file;
std::string e9_file;
fail::Logger m_log; fail::Logger m_log;
fail::ElfReader *m_elf; fail::ElfReader *m_elf;