ecos: bugfix: cyg_test_output may be called before FI
This is a pretty old bug that unfortunately affects both DSN 2013 and SOBRES 2013 results. Change-Id: I64a2790a4d55515a23a34d108be99646d5dd345d
This commit is contained in:
@ -264,6 +264,32 @@ bool EcosKernelTestExperiment::performTrace(guest_address_t addr_entry, guest_ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
#else // !PREREQUISITES
|
#else // !PREREQUISITES
|
||||||
|
void EcosKernelTestExperiment::handle_func_test_output(bool &test_failed, bool& test_passed)
|
||||||
|
{
|
||||||
|
// 1st argument of cyg_test_output shows what has happened (FAIL or PASS)
|
||||||
|
address_t stack_ptr = simulator.getCPU(0).getStackPointer(); // esp
|
||||||
|
int32_t cyg_test_output_argument = simulator.getMemoryManager().getByte(stack_ptr + 4); // 1st argument is at esp+4
|
||||||
|
|
||||||
|
log << "cyg_test_output_argument (#1): " << cyg_test_output_argument << endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef enum {
|
||||||
|
CYGNUM_TEST_FAIL,
|
||||||
|
CYGNUM_TEST_PASS,
|
||||||
|
CYGNUM_TEST_EXIT,
|
||||||
|
CYGNUM_TEST_INFO,
|
||||||
|
CYGNUM_TEST_GDBCMD,
|
||||||
|
CYGNUM_TEST_NA
|
||||||
|
} Cyg_test_code;
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (cyg_test_output_argument == 0) {
|
||||||
|
test_failed = true;
|
||||||
|
} else if (cyg_test_output_argument == 1) {
|
||||||
|
test_passed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool EcosKernelTestExperiment::faultInjection() {
|
bool EcosKernelTestExperiment::faultInjection() {
|
||||||
log << "STEP 3: The actual experiment." << endl;
|
log << "STEP 3: The actual experiment." << endl;
|
||||||
|
|
||||||
@ -355,10 +381,21 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
job.close();
|
job.close();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// the outcome of ecos' test case
|
||||||
|
bool ecos_test_passed = false;
|
||||||
|
bool ecos_test_failed = false;
|
||||||
|
|
||||||
// reaching finish() could happen before OR after FI
|
// reaching finish() could happen before OR after FI
|
||||||
BPSingleListener func_finish(addr_finish);
|
BPSingleListener func_finish(addr_finish);
|
||||||
simulator.addListener(&func_finish);
|
simulator.addListener(&func_finish);
|
||||||
|
|
||||||
|
// reaching cyg_test_output() could happen before OR after FI
|
||||||
|
// eCos' test output function, which will show if the test PASSed or FAILed
|
||||||
|
BPSingleListener func_test_output(addr_test_output);
|
||||||
|
simulator.addListener(&func_test_output);
|
||||||
|
|
||||||
|
BaseListener* ev;
|
||||||
|
|
||||||
// no need to wait if offset is 0
|
// no need to wait if offset is 0
|
||||||
if (instr_offset > 0) {
|
if (instr_offset > 0) {
|
||||||
// XXX could be improved with intermediate states (reducing runtime until injection)
|
// XXX could be improved with intermediate states (reducing runtime until injection)
|
||||||
@ -366,12 +403,17 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
bp.setCounter(instr_offset);
|
bp.setCounter(instr_offset);
|
||||||
simulator.addListener(&bp);
|
simulator.addListener(&bp);
|
||||||
|
|
||||||
// finish() before FI?
|
while (true) {
|
||||||
if (simulator.resume() == &func_finish) {
|
ev = simulator.resume();
|
||||||
log << "experiment reached finish() before FI" << endl;
|
if (ev == &func_test_output) {
|
||||||
|
// re-add this listener
|
||||||
// wait for bp
|
simulator.addListener(&func_test_output);
|
||||||
simulator.resume();
|
handle_func_test_output(ecos_test_failed, ecos_test_passed);
|
||||||
|
} else if (ev == &func_finish) {
|
||||||
|
log << "experiment reached finish() before FI" << endl;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,10 +508,6 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
//ev_end.setCounter(instr_counter - instr_offset + ECOS_RECOVERYINSTR);
|
//ev_end.setCounter(instr_counter - instr_offset + ECOS_RECOVERYINSTR);
|
||||||
//simulator.addListener(&ev_end);
|
//simulator.addListener(&ev_end);
|
||||||
|
|
||||||
// eCos' test output function, which will show if the test PASSed or FAILed
|
|
||||||
BPSingleListener func_test_output(addr_test_output);
|
|
||||||
simulator.addListener(&func_test_output);
|
|
||||||
|
|
||||||
// function called by ecc aspects, when an uncorrectable error is detected
|
// function called by ecc aspects, when an uncorrectable error is detected
|
||||||
BPSingleListener func_ecc_panic(addr_panic);
|
BPSingleListener func_ecc_panic(addr_panic);
|
||||||
if (addr_panic != ADDR_INV) {
|
if (addr_panic != ADDR_INV) {
|
||||||
@ -486,41 +524,13 @@ bool EcosKernelTestExperiment::faultInjection() {
|
|||||||
simulator.addFlow(&tp);
|
simulator.addFlow(&tp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// the outcome of ecos' test case
|
|
||||||
bool ecos_test_passed = false;
|
|
||||||
bool ecos_test_failed = false;
|
|
||||||
|
|
||||||
BaseListener* ev;
|
|
||||||
|
|
||||||
// wait until experiment-terminating event occurs
|
// wait until experiment-terminating event occurs
|
||||||
while (true) {
|
while (true) {
|
||||||
ev = simulator.resume();
|
ev = simulator.resume();
|
||||||
if (ev == &func_test_output) {
|
if (ev == &func_test_output) {
|
||||||
// re-add this listener
|
// re-add this listener
|
||||||
simulator.addListener(&func_test_output);
|
simulator.addListener(&func_test_output);
|
||||||
|
handle_func_test_output(ecos_test_failed, ecos_test_passed);
|
||||||
// 1st argument of cyg_test_output shows what has happened (FAIL or PASS)
|
|
||||||
address_t stack_ptr = simulator.getCPU(0).getStackPointer(); // esp
|
|
||||||
int32_t cyg_test_output_argument = simulator.getMemoryManager().getByte(stack_ptr + 4); // 1st argument is at esp+4
|
|
||||||
|
|
||||||
log << "cyg_test_output_argument (#1): " << cyg_test_output_argument << endl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
typedef enum {
|
|
||||||
CYGNUM_TEST_FAIL,
|
|
||||||
CYGNUM_TEST_PASS,
|
|
||||||
CYGNUM_TEST_EXIT,
|
|
||||||
CYGNUM_TEST_INFO,
|
|
||||||
CYGNUM_TEST_GDBCMD,
|
|
||||||
CYGNUM_TEST_NA
|
|
||||||
} Cyg_test_code;
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (cyg_test_output_argument == 0) {
|
|
||||||
ecos_test_failed = true;
|
|
||||||
} else if (cyg_test_output_argument == 1) {
|
|
||||||
ecos_test_passed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// special case: except1 and clockcnv actively generate traps
|
// special case: except1 and clockcnv actively generate traps
|
||||||
} else if (ev == &ev_trap
|
} else if (ev == &ev_trap
|
||||||
|
|||||||
@ -31,4 +31,6 @@ public:
|
|||||||
fail::guest_address_t& text_end,
|
fail::guest_address_t& text_end,
|
||||||
fail::guest_address_t& data_start,
|
fail::guest_address_t& data_start,
|
||||||
fail::guest_address_t& data_end);
|
fail::guest_address_t& data_end);
|
||||||
|
|
||||||
|
void handle_func_test_output(bool &test_failed, bool& test_passed);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user