From 6d51da52bbfec799d7971f1bda9a01cb8456996b Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Fri, 24 Aug 2018 10:48:02 +0100 Subject: [PATCH] gem5: add m5 fail 1 to /m5op.out Document that m5 fail is not actually exiting status 1 on fs.py. --- README.adoc | 44 ++++++++++++++++++++++++++++++++++---- kernel_module/user/m5ops.c | 35 +++++++++++++++++++----------- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/README.adoc b/README.adoc index 24fb758..f1d0b03 100644 --- a/README.adoc +++ b/README.adoc @@ -8221,16 +8221,36 @@ It is possible to guess what most tools do from the corresponding <>, but ===== m5 exit -Quit gem5 with exit status 0. +End the simulation. + +Sane Python scripts will exit gem5 with status 0, which is what `fs.py` does. ===== m5 fail -Quit gem5 with the given exit status. +End the simulation with a failure exit event: .... m5 fail 1 .... +Sane Python scripts would use that as the exit status of gem5, which would be useful for testing purposes, but `fs.py` at 200281b08ca21f0d2678e23063f088960d3c0819 just prints an error message: + +.... +Simulated exit code not 0! Exit code is 1 +.... + +and exits with status 0. + +TODO: it used to exit non 0, be like that, but it actually got changed to just print the message. Why? https://gem5-review.googlesource.com/c/public/gem5/+/4880 + +`m5 fail` is just a superset of `m5 exit`, which is just: + +.... +m5 fail 0 +.... + +as can be seen from the source: https://github.com/gem5/gem5/blob/50a57c0376c02c912a978c4443dd58caebe0f173/src/sim/pseudo_inst.cc#L303 + ===== m5 writefile Send a guest file to the host. <<9p>> is a more advanced alternative. @@ -8294,10 +8314,13 @@ The executable `/m5ops.out` illustrates how to hard code with inline assembly th .... # checkpoint /m5ops.out c + # dumpstats /m5ops.out d -# dump exit + +# exit /m5ops.out e + # dump resetstats /m5ops.out r .... @@ -8359,7 +8382,20 @@ Finally, `m5.c` calls the defined functions as in: m5_exit(ints[0]); .... -Therefore, the runtime "argument" that gets passed to the instruction, e.g. the desired exit status in the case of `exit`, gets passed directly through the link:https://en.wikipedia.org/wiki/Calling_convention#ARM_(A64)[aarch64 calling convention]. +Therefore, the runtime "argument" that gets passed to the instruction, e.g. the delay in ticks until the exit for `m5 exit`, gets passed directly through the link:https://en.wikipedia.org/wiki/Calling_convention#ARM_(A64)[aarch64 calling convention]. + +Keep in mind that for all archs, `m5.c` does the calls with 64-bit integers: + +.... +uint64_t ints[2] = {0,0}; +parse_int_args(argc, argv, ints, argc); +m5_fail(ints[1], ints[0]); +.... + +Therefore, for example: + +* aarch64 uses `x0` for the first argument and `x1` for the second, since each is 64 bits log already +* arm uses `r0` and `r1` for the first argument, and `r2` and `r3` for the second, since each register is only 32 bits long That convention specifies that `x0` to `x7` contain the function arguments, so `x0` contains the first argument, and `x1` the second. diff --git a/kernel_module/user/m5ops.c b/kernel_module/user/m5ops.c index e192724..d8bc73c 100644 --- a/kernel_module/user/m5ops.c +++ b/kernel_module/user/m5ops.c @@ -6,36 +6,44 @@ #define ENABLED 1 #if defined(__arm__) -static void m5_checkpoint() +static void m5_checkpoint(void) { - __asm__ __volatile__ ("mov r0, #0; mov r1, #0; .inst 0xEE000110 | (0x43 << 16);"); + __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #0; mov r3, #0; .inst 0xEE000110 | (0x43 << 16);"); }; -static void m5_dump_stats() +static void m5_dump_stats(void) { - __asm__ __volatile__ ("mov r0, #0; mov r1, #0; .inst 0xEE000110 | (0x41 << 16);"); + __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #0; mov r3, #0; .inst 0xEE000110 | (0x41 << 16);"); }; static void m5_exit() { __asm__ __volatile__ ("mov r0, #0; .inst 0xEE000110 | (0x21 << 16);"); }; -static void m5_reset_stats() +static void m5_fail_1(void) { - __asm__ __volatile__ ("mov r0, #0; mov r1, #0; .inst 0xEE000110 | (0x40 << 16);"); + __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #1; mov r3, #0; .inst 0xEE000110 | (0x22 << 16);"); +}; +static void m5_reset_stats(void) +{ + __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #0; mov r3, #0; .inst 0xEE000110 | (0x40 << 16);"); }; #elif defined(__aarch64__) -static void m5_checkpoint() +static void m5_checkpoint(void) { __asm__ __volatile__ ("mov x0, #0; mov x1, #0; .inst 0xFF000110 | (0x43 << 16);"); }; -static void m5_dump_stats() +static void m5_dump_stats(void) { __asm__ __volatile__ ("mov x0, #0; mov x1, #0; .inst 0xFF000110 | (0x41 << 16);"); }; -static void m5_exit() +static void m5_exit(void) { __asm__ __volatile__ ("mov x0, #0; .inst 0XFF000110 | (0x21 << 16);"); }; -static void m5_reset_stats() +static void m5_fail_1(void) +{ + __asm__ __volatile__ ("mov x0, #0; mov x1, #1; .inst 0xFF000110 | (0x22 << 16);"); +}; +static void m5_reset_stats(void) { __asm__ __volatile__ ("mov x0, #0; mov x1, #0; .inst 0XFF000110 | (0x40 << 16);"); }; @@ -62,14 +70,17 @@ void switch (action) { case 'c': - m5_checkpoint(0, 0); + m5_checkpoint(); break; case 'd': - m5_dump_stats(0, 0); + m5_dump_stats(); break; case 'e': m5_exit(); break; + case 'f': + m5_fail_1(); + break; case 'r': m5_reset_stats(); break;