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:
@ -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;
|
||||||
|
|||||||
@ -73,8 +73,12 @@ private:
|
|||||||
void logInjection(fail::Logger &log, const L4SysExperimentData ¶m);
|
void logInjection(fail::Logger &log, const L4SysExperimentData ¶m);
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user