diff --git a/src/experiments/l4-sys/experiment.cc b/src/experiments/l4-sys/experiment.cc index 5e3ef921..a859b35b 100644 --- a/src/experiments/l4-sys/experiment.cc +++ b/src/experiments/l4-sys/experiment.cc @@ -122,11 +122,13 @@ void L4SysExperiment::logInjection(Logger &log, << ")" << " bit " << bit_offset << endl; } -void L4SysExperiment::singleStep() { - BPSingleListener singlestepping_event(ANY_ADDR, L4SYS_ADDRESS_SPACE); +BaseListener *L4SysExperiment::singleStep(bool preserveAddressSpace) { + address_t aspace = (preserveAddressSpace ? L4SYS_ADDRESS_SPACE : ANY_ADDR); + BPSingleListener singlestepping_event(ANY_ADDR, aspace); simulator.addListener(&singlestepping_event); - waitIOOrOther(false); + BaseListener *ev = waitIOOrOther(false); simulator.removeListener(&singlestepping_event); + return ev; } 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)); // execute the faulty instruction, then return - singleStep(); + singleStep(false); //restore the old instruction memcpy(oldInstr, &backupInstr, sizeof(bxInstruction_c)); @@ -461,7 +463,7 @@ bool L4SysExperiment::run() { if (opcount == 0) { // try the next instruction - singleStep(); + singleStep(true); } else { // assign the necessary variables rnd = rand() % opcount; @@ -527,24 +529,43 @@ bool L4SysExperiment::run() { 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 - singleStep(); + BaseListener *triggeredListener = singleStep(true); + simulator.removeListener(&schedTimeout); - // restore - if (rnd == 0) { - // output register - do the fault injection here - if (exchg_reg >= 0) { - // write the result into the wrong local register - regdata_t newdata = rm.getRegister(bochs_reg)->getData(); - rm.getRegister(exchg_reg)->setData(newdata); + if (triggeredListener != &schedTimeout) { + // restore the register if we are still in the thread + if (rnd == 0) { + // output register - do the fault injection here + if (exchg_reg >= 0) { + // write the result into the wrong local register + 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 - rm.getRegister(bochs_reg)->setData(data); + // restore the actual value of the register + // in reality, it would never have been overwritten + rm.getRegister(bochs_reg)->setData(data); + } else { + // 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); } else if (exp_type == param.msg.ALUINSTR) { @@ -555,7 +576,7 @@ bool L4SysExperiment::run() { while (!aluInstrObject.isALUInstruction( currInstr = simulator.getCurrentInstruction()) && simulator.getRegisterManager().getInstructionPointer() != L4SYS_FUNC_EXIT) { - singleStep(); + singleStep(true); } if (simulator.getRegisterManager().getInstructionPointer() == L4SYS_FUNC_EXIT) { @@ -622,27 +643,27 @@ bool L4SysExperiment::run() { */ if (ev == &ev_done) { 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); } else { - log << dec << "Result WRONG" << endl; + log << "Result WRONG" << endl; param.msg.set_resulttype(param.msg.WRONG); param.msg.set_output(sanitised(output.c_str())); } } else if (ev == &ev_incomplete) { - log << dec << "Result INCOMPLETE" << endl; + log << "Result INCOMPLETE" << endl; param.msg.set_resulttype(param.msg.INCOMPLETE); param.msg.set_resultdata( simulator.getRegisterManager().getInstructionPointer()); param.msg.set_output(sanitised(output.c_str())); } else if (ev == &ev_timeout) { - log << hex << "Result TIMEOUT" << endl; + 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())); } else { - log << dec << "Result WTF?" << endl; + log << "Result WTF?" << endl; param.msg.set_resulttype(param.msg.UNKNOWN); param.msg.set_resultdata( simulator.getRegisterManager().getInstructionPointer()); @@ -657,9 +678,8 @@ bool L4SysExperiment::run() { simulator.clearListeners(); m_jc.sendResult(param); #endif -#ifdef HEADLESS_EXPERIMENT + simulator.terminate(0); -#endif // experiment successfully conducted return true; diff --git a/src/experiments/l4-sys/experiment.hpp b/src/experiments/l4-sys/experiment.hpp index 6ff98eae..96b70b45 100644 --- a/src/experiments/l4-sys/experiment.hpp +++ b/src/experiments/l4-sys/experiment.hpp @@ -73,8 +73,12 @@ private: void logInjection(fail::Logger &log, const L4SysExperimentData ¶m); /** * 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 * @param oldInstr address of the instruction to be replaced diff --git a/src/experiments/l4-sys/experimentInfo.hpp b/src/experiments/l4-sys/experimentInfo.hpp index b56fd4c3..94dfc7fe 100644 --- a/src/experiments/l4-sys/experimentInfo.hpp +++ b/src/experiments/l4-sys/experimentInfo.hpp @@ -19,7 +19,6 @@ #define L4SYS_CORRECT_OUTPUT "golden.out" // flags -#define HEADLESS_EXPERIMENT // 0 - preparation complete // >0 - next step to execute #define PREPARATION_STEP 0