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:
committed by
Horst Schirmeier
parent
ad558abeb6
commit
d46b81eb3d
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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();
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user