diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index ea5949efc..406f9ef0f 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -27,6 +27,7 @@ # # Authors: Lisa Hsu +import sys from os import getcwd from os.path import join as joinpath @@ -505,3 +506,5 @@ def run(options, root, testsys, cpu_class): print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_cause) if options.checkpoint_at_end: m5.checkpoint(joinpath(cptdir, "cpt.%d")) + + sys.exit(exit_event.getCode()) diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 3b187d625..711be0bd5 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -157,6 +157,9 @@ 0x21: m5exit({{ PseudoInst::m5exit(xc->tcBase(), Rdi); }}, IsNonSpeculative); + 0x22: m5fail({{ + PseudoInst::m5fail(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); 0x30: m5initparam({{ Rax = PseudoInst::initParam(xc->tcBase()); }}, IsNonSpeculative); diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index aafa5672b..a57bdb2ce 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -218,6 +218,13 @@ m5exit(ThreadContext *tc, Tick delay) exitSimLoop("m5_exit instruction encountered", 0, when); } +void +m5fail(ThreadContext *tc, Tick delay, uint64_t code) +{ + Tick when = curTick() + delay * SimClock::Int::ns; + exitSimLoop("m5_fail instruction encountered", code, when); +} + void loadsymbol(ThreadContext *tc) { diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index 4a6493a66..efcd44a69 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -54,6 +54,7 @@ uint64_t initParam(ThreadContext *xc); uint64_t rpns(ThreadContext *tc); void wakeCPU(ThreadContext *tc, uint64_t cpuid); void m5exit(ThreadContext *tc, Tick delay); +void m5fail(ThreadContext *tc, Tick delay, uint64_t code); void resetstats(ThreadContext *tc, Tick delay, Tick period); void dumpstats(ThreadContext *tc, Tick delay, Tick period); void dumpresetstats(ThreadContext *tc, Tick delay, Tick period); diff --git a/util/m5/m5.c b/util/m5/m5.c index e9fe8f1f3..021816ce3 100644 --- a/util/m5/m5.c +++ b/util/m5/m5.c @@ -134,6 +134,15 @@ do_exit(int argc, char *argv[]) m5_exit(ints[0]); } +void +do_fail(int argc, char *argv[]) +{ + if (argc < 1 || argc > 2) + usage(); + + m5_fail((argc > 1) ? strtoul(argv[1], NULL, 0) : 0, strtoul(argv[0], NULL, 0)); +} + void do_reset_stats(int argc, char *argv[]) { @@ -273,6 +282,7 @@ struct MainFunc struct MainFunc mainfuncs[] = { { "exit", do_exit, "[delay]" }, + { "fail", do_fail, " [delay]" }, { "resetstats", do_reset_stats, "[delay [period]]" }, { "dumpstats", do_dump_stats, "[delay [period]]" }, { "dumpresetstats", do_dump_reset_stats, "[delay [period]]" }, diff --git a/util/m5/m5op.h b/util/m5/m5op.h index 9e693258e..9df9a7429 100644 --- a/util/m5/m5op.h +++ b/util/m5/m5op.h @@ -47,6 +47,7 @@ uint64_t rpns(); void wakeCPU(uint64_t cpuid); void m5_exit(uint64_t ns_delay); +void m5_fail(uint64_t ns_delay, uint64_t code); uint64_t m5_initparam(void); void m5_checkpoint(uint64_t ns_delay, uint64_t ns_period); void m5_reset_stats(uint64_t ns_delay, uint64_t ns_period); diff --git a/util/m5/m5op_x86.S b/util/m5/m5op_x86.S index 93eacc24d..2c25785e6 100644 --- a/util/m5/m5op_x86.S +++ b/util/m5/m5op_x86.S @@ -48,6 +48,7 @@ TWO_BYTE_OP(quiesceCycle, quiescecycle_func) TWO_BYTE_OP(quiesceTime, quiescetime_func) TWO_BYTE_OP(rpns, rpns_func) TWO_BYTE_OP(m5_exit, exit_func) +TWO_BYTE_OP(m5_fail, fail_func) TWO_BYTE_OP(m5_initparam, initparam_func) TWO_BYTE_OP(m5_loadsymbol, loadsymbol_func) TWO_BYTE_OP(m5_reset_stats, resetstats_func) diff --git a/util/m5/m5ops.h b/util/m5/m5ops.h index f08524014..8ff1ac42f 100644 --- a/util/m5/m5ops.h +++ b/util/m5/m5ops.h @@ -40,6 +40,7 @@ #define deprecated2_func 0x11 // obsolete ivle #define deprecated3_func 0x20 // deprecated exit function #define exit_func 0x21 +#define fail_func 0x22 #define initparam_func 0x30 #define loadsymbol_func 0x31 #define resetstats_func 0x40