From ee07553278f0680aa448e7c6385df7ed748039af Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Tue, 29 May 2018 00:21:04 +0100 Subject: [PATCH] mops: document hardcoding them into benchmarks --- README.adoc | 59 ++++++++++++++++++++++++++++++------- kernel_module/user/m5ops.c | 60 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 kernel_module/user/m5ops.c diff --git a/README.adoc b/README.adoc index 636f88b..f385123 100644 --- a/README.adoc +++ b/README.adoc @@ -6127,23 +6127,34 @@ And a second instance: TODO Now we just need to network them up to have some more fun! See dist-gem5: http://publish.illinois.edu/icsl-pdgem5/ -=== m5 +=== m5ops -`m5` is a guest command line utility that is installed and run on the guest. +m5ops are magic instructions which lead gem5 to do magic things, like quitting or dumping stats. -Its source is present under the gem5 main tree. +Documentation: http://gem5.org/M5ops -It generates magic instructions, which lead gem5 to do magic things, like `dumpstats` or `exit`. +There are two main ways to use m5ops: -It is however under-documented, so let's document some of its capabilities here. +* <> +* <> -Part of those explanations could be deduced from the documentation of the magic instructions themselves: http://gem5.org/M5ops +`m5` is an officially supported tool, and requires zero integration work for you, and no recompilation of your benchmarks of interest. -==== m5 exit +However it is more intrusive that hardcoding the m5ops instructions into the benchmark itself, since it requires a system call on the guest. + +==== m5 + +`m5` is a guest command line utility that is installed and run on the guest, that serves as a CLI front-end for the <> + +Its source is present in the gem5 tree: https://github.com/gem5/gem5/blob/6925bf55005c118dc2580ba83e0fa10b31839ef9/util/m5/m5.c + +It is possible to guess what most tools do from the corresponding <>, but let's at least document the less obvious ones here. + +===== m5 exit Quit gem5 with exit status 0. -==== m5 fail +===== m5 fail Quit gem5 with the given exit status. @@ -6151,7 +6162,7 @@ Quit gem5 with the given exit status. m5 fail 1 .... -==== m5 writefile +===== m5 writefile Send a guest file to the host. <<9p>> is a more advanced alternative. @@ -6174,7 +6185,7 @@ Does not work for subdirectories, gem5 crashes: m5 writefile myfileguest mydirhost/myfilehost .... -==== m5 readfile +===== m5 readfile https://stackoverflow.com/questions/49516399/how-to-use-m5-readfile-and-m5-execfile-in-gem5/49538051#49538051 @@ -6190,7 +6201,7 @@ Guest: m5 readfile .... -==== m5 execfile +===== m5 execfile Host: @@ -6207,6 +6218,32 @@ chmod +x /tmp/execfile m5 execfile .... +==== m5ops instructions + +The executable m5ops illustrates how to hard code inline assembly the most useful m5ops that you are most likely to hack into the benchmark you are analysing: + +.... +# checkpoint +/m5ops.out c +# dumpstats +/m5ops.out d +# dump exit +/m5ops.out e +# dump resetstats +/m5ops.out r +.... + +That executable is of course a subset of <> and useless by itself: its goal is only illustrate how to hardcode some <> yourself. + +In theory, the cleanest way to add m5ops to your benchmarks would be to do exactly what the `m5` tool does: + +* include `include/gem5/m5ops.h` +* link with the `.o` file under `util/m5` for the correct arch, e.g. `m5op_arm_A64.o` for aarch64. + +However, I think it is usually not worth the trouble of hacking up the build system of the benchmark to do this, and I recommend just hardcoding in a few raw instructions here and there, and managing it with version control + `sed`. + +Related: https://www.mail-archive.com/gem5-users@gem5.org/msg15418.html + === gem5 arm Linux kernel patches https://gem5.googlesource.com/arm/linux/ contains an ARM Linux kernel fork with a few gem5 specific Linux kernel patches on top of mainline created by ARM Holdings. diff --git a/kernel_module/user/m5ops.c b/kernel_module/user/m5ops.c new file mode 100644 index 0000000..f22a8da --- /dev/null +++ b/kernel_module/user/m5ops.c @@ -0,0 +1,60 @@ +#include +#include +#include + +#define ENABLED 1 +#if defined(__aarch64__) +static void m5_checkpoint(uint64_t x, uint64_t y) +{ + __asm__ __volatile__ (".inst 0xff430110;":: "r" (x), "r" (y)); +}; +static void m5_dump_stats(uint64_t x, uint64_t y) +{ + __asm__ __volatile__ (".inst 0xff410110;":: "r" (x), "r" (y)); +}; +static void m5_exit(uint64_t x) +{ + __asm__ __volatile__ (".inst 0xff210110;":: "r" (x)); +}; +static void m5_reset_stats(uint64_t x, uint64_t y) +{ + __asm__ __volatile__ (".inst 0xff400110;":: "r" (x), "r" (y)); +}; +#else +#undef ENABLED +#define ENABLED 0 +#endif + +int main( +#if ENABLED +int argc, char **argv +#else +void +#endif +) +{ +#if defined(__aarch64__) + char action; + if (argc > 1) { + action = argv[1][0]; + } else { + action = 'e'; + } + switch (action) + { + case 'c': + m5_checkpoint(0, 0); + break; + case 'd': + m5_dump_stats(0, 0); + break; + case 'e': + m5_exit(0); + break; + case 'r': + m5_reset_stats(0, 0); + break; + } +#endif + return EXIT_SUCCESS; +}