Handled a kind of wicked error case which nevertheless happens quite frequently

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1917 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
unzner
2012-11-11 11:37:08 +00:00
parent 35b1d0203e
commit 1b5bbba0e5
3 changed files with 52 additions and 29 deletions

View File

@ -122,11 +122,13 @@ void L4SysExperiment::logInjection(Logger &log,
<< ")" << " bit " << bit_offset << endl; << ")" << " bit " << bit_offset << endl;
} }
void L4SysExperiment::singleStep() { BaseListener *L4SysExperiment::singleStep(bool preserveAddressSpace) {
BPSingleListener singlestepping_event(ANY_ADDR, L4SYS_ADDRESS_SPACE); address_t aspace = (preserveAddressSpace ? L4SYS_ADDRESS_SPACE : ANY_ADDR);
BPSingleListener singlestepping_event(ANY_ADDR, aspace);
simulator.addListener(&singlestepping_event); simulator.addListener(&singlestepping_event);
waitIOOrOther(false); BaseListener *ev = waitIOOrOther(false);
simulator.removeListener(&singlestepping_event); simulator.removeListener(&singlestepping_event);
return ev;
} }
void L4SysExperiment::injectInstruction(bxInstruction_c *oldInstr, bxInstruction_c *newInstr) { void L4SysExperiment::injectInstruction(bxInstruction_c *oldInstr, bxInstruction_c *newInstr) {
@ -136,7 +138,7 @@ void L4SysExperiment::injectInstruction(bxInstruction_c *oldInstr, bxInstruction
memcpy(oldInstr, newInstr, sizeof(bxInstruction_c)); memcpy(oldInstr, newInstr, sizeof(bxInstruction_c));
// execute the faulty instruction, then return // execute the faulty instruction, then return
singleStep(); singleStep(false);
//restore the old instruction //restore the old instruction
memcpy(oldInstr, &backupInstr, sizeof(bxInstruction_c)); memcpy(oldInstr, &backupInstr, sizeof(bxInstruction_c));
@ -461,7 +463,7 @@ bool L4SysExperiment::run() {
if (opcount == 0) { if (opcount == 0) {
// try the next instruction // try the next instruction
singleStep(); singleStep(true);
} else { } else {
// assign the necessary variables // assign the necessary variables
rnd = rand() % opcount; rnd = rand() % opcount;
@ -527,24 +529,43 @@ bool L4SysExperiment::run() {
rm.getRegister(bochs_reg)->setData(newdata); rm.getRegister(bochs_reg)->setData(newdata);
} }
/* prepare for the case that the kernel panics and never
switches back to this thread by introducing a scheduling timeout
of 10 seconds */
TimerListener schedTimeout(10000);
simulator.addListener(&schedTimeout);
// execute the instruction // execute the instruction
singleStep(); BaseListener *triggeredListener = singleStep(true);
simulator.removeListener(&schedTimeout);
// restore if (triggeredListener != &schedTimeout) {
if (rnd == 0) { // restore the register if we are still in the thread
// output register - do the fault injection here if (rnd == 0) {
if (exchg_reg >= 0) { // output register - do the fault injection here
// write the result into the wrong local register if (exchg_reg >= 0) {
regdata_t newdata = rm.getRegister(bochs_reg)->getData(); // write the result into the wrong local register
rm.getRegister(exchg_reg)->setData(newdata); regdata_t newdata = rm.getRegister(bochs_reg)->getData();
rm.getRegister(exchg_reg)->setData(newdata);
}
// otherwise, just assume it is stored in an unused register
} }
// otherwise, just assume it is stored in an unused register // restore the actual value of the register
} // in reality, it would never have been overwritten
// restore the actual value of the register rm.getRegister(bochs_reg)->setData(data);
// in reality, it would never have been overwritten } else {
rm.getRegister(bochs_reg)->setData(data); // otherwise we just assume this thread is never scheduled again
log << "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()));
param.msg.set_details("Timed out immediately after injecting");
// and log the injection m_jc.sendResult(param);
simulator.terminate(0);
}
// log the injection
logInjection(log, param); logInjection(log, param);
} else if (exp_type == param.msg.ALUINSTR) { } else if (exp_type == param.msg.ALUINSTR) {
@ -555,7 +576,7 @@ bool L4SysExperiment::run() {
while (!aluInstrObject.isALUInstruction( while (!aluInstrObject.isALUInstruction(
currInstr = simulator.getCurrentInstruction()) && currInstr = simulator.getCurrentInstruction()) &&
simulator.getRegisterManager().getInstructionPointer() != L4SYS_FUNC_EXIT) { simulator.getRegisterManager().getInstructionPointer() != L4SYS_FUNC_EXIT) {
singleStep(); singleStep(true);
} }
if (simulator.getRegisterManager().getInstructionPointer() == L4SYS_FUNC_EXIT) { if (simulator.getRegisterManager().getInstructionPointer() == L4SYS_FUNC_EXIT) {
@ -622,27 +643,27 @@ bool L4SysExperiment::run() {
*/ */
if (ev == &ev_done) { if (ev == &ev_done) {
if (strcmp(output.c_str(), golden_run.c_str()) == 0) { if (strcmp(output.c_str(), golden_run.c_str()) == 0) {
log << dec << "Result DONE" << endl; log << "Result DONE" << endl;
param.msg.set_resulttype(param.msg.DONE); param.msg.set_resulttype(param.msg.DONE);
} else { } else {
log << dec << "Result WRONG" << endl; log << "Result WRONG" << endl;
param.msg.set_resulttype(param.msg.WRONG); param.msg.set_resulttype(param.msg.WRONG);
param.msg.set_output(sanitised(output.c_str())); param.msg.set_output(sanitised(output.c_str()));
} }
} else if (ev == &ev_incomplete) { } else if (ev == &ev_incomplete) {
log << dec << "Result INCOMPLETE" << endl; log << "Result INCOMPLETE" << endl;
param.msg.set_resulttype(param.msg.INCOMPLETE); param.msg.set_resulttype(param.msg.INCOMPLETE);
param.msg.set_resultdata( param.msg.set_resultdata(
simulator.getRegisterManager().getInstructionPointer()); simulator.getRegisterManager().getInstructionPointer());
param.msg.set_output(sanitised(output.c_str())); param.msg.set_output(sanitised(output.c_str()));
} else if (ev == &ev_timeout) { } else if (ev == &ev_timeout) {
log << hex << "Result TIMEOUT" << endl; log << "Result TIMEOUT" << endl;
param.msg.set_resulttype(param.msg.TIMEOUT); param.msg.set_resulttype(param.msg.TIMEOUT);
param.msg.set_resultdata( param.msg.set_resultdata(
simulator.getRegisterManager().getInstructionPointer()); simulator.getRegisterManager().getInstructionPointer());
param.msg.set_output(sanitised(output.c_str())); param.msg.set_output(sanitised(output.c_str()));
} else { } else {
log << dec << "Result WTF?" << endl; log << "Result WTF?" << endl;
param.msg.set_resulttype(param.msg.UNKNOWN); param.msg.set_resulttype(param.msg.UNKNOWN);
param.msg.set_resultdata( param.msg.set_resultdata(
simulator.getRegisterManager().getInstructionPointer()); simulator.getRegisterManager().getInstructionPointer());
@ -657,9 +678,8 @@ bool L4SysExperiment::run() {
simulator.clearListeners(); simulator.clearListeners();
m_jc.sendResult(param); m_jc.sendResult(param);
#endif #endif
#ifdef HEADLESS_EXPERIMENT
simulator.terminate(0); simulator.terminate(0);
#endif
// experiment successfully conducted // experiment successfully conducted
return true; return true;

View File

@ -73,8 +73,12 @@ private:
void logInjection(fail::Logger &log, const L4SysExperimentData &param); void logInjection(fail::Logger &log, const L4SysExperimentData &param);
/** /**
* Proceeds by one single instruction. * Proceeds by one single instruction.
* @param preserveAddressSpace if set, the address space of the next instruction
* must match with the current address space
* (for example, this is important when debugging in the kernel)
* @returns the listener that was triggered, in case there were more than one
*/ */
void singleStep(); fail::BaseListener *singleStep(bool preserveAddressSpace);
/** /**
* Injects a new instruction into the Bochs instruction stream and restores the previous one * Injects a new instruction into the Bochs instruction stream and restores the previous one
* @param oldInstr address of the instruction to be replaced * @param oldInstr address of the instruction to be replaced

View File

@ -19,7 +19,6 @@
#define L4SYS_CORRECT_OUTPUT "golden.out" #define L4SYS_CORRECT_OUTPUT "golden.out"
// flags // flags
#define HEADLESS_EXPERIMENT
// 0 - preparation complete // 0 - preparation complete
// >0 - next step to execute // >0 - next step to execute
#define PREPARATION_STEP 0 #define PREPARATION_STEP 0