| The m5 utility provides a command line and library interface for gem5 |
| operations. |
| |
| These operations are requested by the simulated software through some special |
| behavior which is recognized by gem5. gem5 will then perform the requested |
| operation which is outside the normal behavior of the simulated system. |
| |
| |
| |
| # Trigger mechanisms |
| |
| There are a few different ways the simulated software can let gem5 know it |
| wants to perform an operation. Different CPU models have different constraints |
| depending on how they're implemented, and may not support all of these |
| different mechanisms. |
| |
| Trigger | Native | KVM | Fast Model |
| -------------|---------|-----|------------ |
| Instruction | Yes | | |
| Address | ARM/X86 | Yes | |
| Semihosting | ARM | | Yes |
| |
| ## "Magic" Instructions |
| |
| This is the oldest trigger mechanism in gem5, and is supported by all of the |
| CPU models which interpret instructions one at a time using gem5's ISA |
| definitions. It works by co-opting instructions which normally are undefined, |
| and redefining them to trigger gem5 operations. Exactly what instructions |
| these are, how they encode what operation they go with, etc., vary from ISA to ISA. |
| |
| When using the KVM CPU models, the instruction stream is executing on actual |
| physical hardware which won't treat these instructions specially. They will |
| retain their old behavior and, most likely, raise an undefined instruction |
| exception if executed. |
| |
| Other external models, like ARM's Fast Model CPUs, also won't treat these |
| instructions specially. |
| |
| ## "Magic" Address Range |
| |
| This mechanism was added for the KVM CPUs so that they could trigger gem5 |
| operations without having to recognize special instructions. This trigger is |
| based on a specially set aside range of physical addresses. When a read or |
| write is targetted at that range, instead of a normal device or memory access, |
| a gem5 operation is triggered. |
| |
| Depending on the ISA, gem5 native CPUs should support this mechanism (see the |
| table below). |
| |
| When using the KVM CPU, the special range of addresses are not registered as |
| memory, and so the KVM virtual machine will exit when they're accessed. gem5 |
| will have a chance to recognize the special address, and can trigger the |
| operation. |
| |
| When using an external model like ARM's Fast Model CPUs, these external |
| accesses will leave the CPU complex, and gem5 will be able to recognize them. |
| Unfortunately if the CPU has multiple threads of execution, gem5 won't be able |
| to tell which the access came from. Also, the memory access may not happen at a |
| precise point in the simulated instruction stream due to binary translation. |
| The architectural state may not be in a consistent state which is suitable to |
| extract arguments or inject a return value. |
| |
| ### Default address range |
| |
| Since x86 has a predictable address space layout, the "magic" address range can |
| be put in a predictable, default location, which is at 0xFFFF0000. |
| |
| On other architectures, notably ARM, the address space is less predictable, and |
| it doesn't make sense to set a default location which won't be valid on all |
| configurations. |
| |
| ## Semihosting |
| |
| This mechanism was added to support ARM's Fast Model CPUs. It extends ARM's |
| semihosting support, a mechanism which was already defined to interrupt normal |
| execution and trigger some sort of behavior in a containing host. |
| |
| On ISAs which support semihosting (only ARM now, and probably going forward), |
| gem5 native CPUs can support semihosting instructions, and so should support |
| the semihosting trigger mechanism. |
| |
| KVM CPUs use real hardware, and so semihosting instructions will not have |
| special behavior and will act like their normal counterparts (HLT, etc.). |
| |
| |
| |
| # Building |
| |
| ## Supported ABIs |
| |
| To build either the command line utility or one of the versions of the library, |
| first identify what ABI(s) you're targetting. |
| |
| ABI | Description | Triggers |
| ---------|--------------|---------- |
| arm64 | 64 bit ARM | instruction, adddress, semihosting |
| arm | 32 bit ARM | instruction |
| thumb | ARM thumb | instruction |
| sparc | 64 bit SPARC | instruction |
| x86 | amd64/x86_64 | instruction, address |
| riscv | 64 bit RISCV | instruction |
| |
| ## SCons |
| |
| The m5 utility uses a scons based build system. gem5 itself also uses SCons, |
| but these builds are (mostly) not related and separate. |
| |
| The SConscript for this utility is set up to use a build directory called |
| "build", similar to gem5 itself. The build directory is structured so that you |
| can ask scons to build a portion of it to help narrow down what you want to |
| build. |
| |
| ### native |
| |
| There is a **build/native** directory which is for some test binaries which |
| test generic functionality and are compiled for the host, whatever that happens |
| to be. These can be run directly, unlike ABI specific tests which may be |
| possible to run directly depending on the host's architecture, but may not. |
| |
| ### ABI |
| |
| The first level subdirectories of the build directory (other than "native", |
| described above) is named after the ABI you're targetting. For instance, build |
| products for x86 would be in the **build/x86** subdirectory. |
| |
| Within an ABI subdirectory will be linked copies of all the source files needed |
| for the build, and also "test" and "out" subdirectories. |
| |
| #### test |
| |
| The "test" subdirectory, for instance **build/x86/test**, holds the test |
| binaries for that ABI in a bin subdirectory, and the results of running those |
| tests (if requested and possible) in a "result" subdirectory. |
| |
| #### out |
| |
| The "out" subdirectory, for instance **build/x86/out**, holds the various final |
| build products. This includes: |
| |
| - m5: The command line utility. |
| - libm5.a: C library. |
| - gem5OpJni.jar, libgem5OpJni.so, jni/gem5Op.class: Java support files. |
| - libgem5OpLua.so: Lua module/library. |
| |
| ## Build options |
| |
| ### SCons variables |
| |
| There are some variables which set build options which need to be controlled on |
| a per ABI level. Currently, these are: |
| |
| - CROSS_COMPILE: The cross compiler prefix. |
| - QEMU_ARCH: The QEMU architecture suffix. |
| |
| To set these for a particular ABI, prefix the variable name with the ABI's name |
| and then a dot. For instance, to set the cross compiler prefix to |
| "x86_64-linux-gnu-" for x86, you would run scons like this: |
| |
| ```shell |
| scons x86.CROSS_COMPILE=x86_64-linux-gnu- build/x86/out/m5 |
| ``` |
| |
| ABI | QEMU_ARCH | CROSS_COMPILE |
| ---------|-----------|--------------------- |
| arm64 | aarch64 | aarch64-linux-gnu- |
| arm | arm | arm-linux-gnueabihf- |
| thumb | arm | arm-linux-gnueabihf- |
| sparc | sparc64 | sparc64-linux-gnu- |
| x86 | x86_64 | |
| riscv | riscv64 | riscv64-unknown-linux-gnu- |
| |
| Note that the default setting for the x86 cross compiler prefix is blank, |
| meaning that the native/host compiler will be used. If building on a non-x86 |
| host, then you'll need to set an appopriate prefix and may be able to clear |
| some other prefix corresponding to that host. |
| |
| ### SCons command line flags |
| |
| --debug-build: Compile with the -g option, and -O0. |
| --run-tests: Allow the test result XML files to be build targets. |
| --verbose: Show build command lines and full command output. |
| |
| ## External dependency detection |
| |
| In some cases, if an external dependency isn't detected, the build will |
| gracefully exclude some targets which depend on it. These include: |
| |
| ### Java support |
| |
| The SConscript will attempt to find the javac and jar programs. If it can't, it |
| will disable building the Java support files. |
| |
| ### Lua support |
| |
| The SConscript will attempt to find lua51 support using pkg-config. If it |
| can't, it will disable building the lua module/library. |
| |
| ### Non-native tests |
| |
| The SConscript will attempt to find various QEMU binaries so that it can run |
| non-native tests using QEMU's application level emulation. The name of the |
| binary it looks for depends on the ABI and is set to qemu-${QEMU_ARCH}. See |
| above for a description of per ABI build variables, including QEMU_ARCH. |
| |
| If it can't find a program with that name, it will disable running non-native |
| test binaries for that ABI. |
| |
| |
| |
| # Testing |
| |
| Tests are based on the googletest system. There are native tests which test |
| mechanisms which are not specific to any ABI and can be run on the host. These |
| are built using the native toolchain. |
| |
| There are also tests for ABI specific mechanisms like the various trigger |
| types. These will be built using the cross compiler configured for a given ABI. |
| These tests can be run in QEMU in its application emulation mode, and the build |
| system can run them automatically if requested and if the required dependencies |
| have been met. |
| |
| The tests for the trigger mechanisms can't count on those mechanisms actually |
| working when running under QEMU, and so will try to set up intercepts which |
| will catch attempts to use them and verify that they were used correctly. When |
| running these tests under gem5, set the RUNNING_IN_GEM5 environment variable |
| which will tell the test to expect the trigger mechanism to actually work. |
| |
| A junit test exists for the Java jar, in a file named 'OpsTest.java'. That test |
| can be run on its own through its own main function, or through the junit |
| framework. |
| |
| |
| |
| # Command line utility |
| |
| The command line utility provides a way of triggering gem5 operations either |
| interactively through a terminal connection to the simulated system, or scripts |
| running within it. |
| |
| ## Calling syntax |
| |
| Any call to the utility should have the following structure: |
| |
| ```shell |
| m5 [call type] <command> [arguments] |
| ``` |
| |
| Call type is optional and selects what trigger mechanism should be used. If |
| it's omitted, the default mechanism will be used. What the default mechanism is |
| varies based on the ABI. |
| |
| ABI | Default call type |
| ---------|------------------- |
| arm64 | instruction |
| arm | instruction |
| thumb | instruction |
| sparc | instruction |
| x86 | address |
| riscv | instruction |
| |
| The default is usually to use a magic instruction, which for most ABIs is the |
| only mechanism that's supported, and is what the m5 utility would |
| tradditionally have used. On x86, the address based mechanism is the default |
| since it's supported on all current CPU types which also support x86. |
| |
| ### Call type |
| |
| To override the default call type, you can use one of these arguments. |
| |
| ```shell |
| --addr [address override] |
| ``` |
| |
| Selects the magic address call type. On most ABIs which don't have a default |
| magic address range, this argument must be followed by the address range to |
| use. On x86 if no address is specified, the default (0xFFFF0000) will be used. |
| |
| ```shell |
| --inst |
| ``` |
| |
| Selects the magic instruction call type. |
| |
| ```shell |
| --semi |
| ``` |
| |
| Selects the semihosting based call type. |
| |
| ### Commands and arguments |
| |
| To see a list of commands and the arguments they support, run the utility with |
| the --help argument. |
| |
| ```shell |
| m5 --help |
| ``` |
| |
| |
| |
| # C library |
| |
| The C library provides a set of functions which can trigger gem5 operations |
| from within compiled programs. |
| |
| ## Building in the library |
| |
| To use the C library, include the header file located at |
| |
| ```shell |
| include/gem5/m5ops.h |
| ``` |
| |
| like so: |
| |
| ```shell |
| #include <gem5/m5ops.h> |
| ``` |
| |
| That will declare the various functions which wrap each of the gem5 operations. |
| It includes another header file located at |
| |
| ```shell |
| include/gem5/asm/generic/m5ops.h |
| ``` |
| |
| using a path relative to include. Be sure that include path will resolve based |
| on the settings of your compiler, or move or modify to fit the existing |
| options. |
| |
| As part of the linking step of your application, link in the libm5.a static |
| library archive which provides the definitions of those functions. |
| |
| ## Trigger mechanisms |
| |
| The bare function name as defined in the header file will use the magic |
| instruction based trigger mechanism, what would have historically been the |
| default. |
| |
| Some macros at the end of the header file will set up other declarations which |
| mirror all of the other definitions, but with an "_addr" and "_semi" suffix. |
| These other versions will trigger the same gem5 operations, but using the |
| "magic" address or semihosting trigger mechanisms. While those functions will |
| be unconditionally declared in the header file, a definition will exist in the |
| library only if that trigger mechanism is supported for that ABI. |
| |
| |
| |
| # Java jar |
| |
| In your java source, import the gem5Op class. |
| |
| ```java |
| import gem5.Ops |
| ``` |
| |
| This class provides a static map named callTypes which map from each of the |
| call type names ("addr", "inst", or "semi") to an Ops instance. That instance |
| will provide a set of methods which trigger each of the gem5 operations using |
| the requested trigger mechanism. The call type "default" maps to whatever the |
| default call type is for the current ABI. |
| |
| ```shell |
| gem5.Ops gem5_ops = gem5.Ops.callTypes.get("default"); |
| long sum = gem5_ops.sum(1, 2, 3, 4, 5, 6); |
| ``` |
| |
| To configure the address based trigger mechanism, you can use these static |
| methods. |
| |
| void setAddr(long addr); |
| Set the address for the "magic" address region. |
| |
| void mapMem(); |
| Map the "magic" physical address region into the process' address space, likely |
| by mmapping the "/dev/mem" device file. |
| |
| void unmapMem(); |
| Unmap the "magic" physical address region that was previously mapped. |
| |
| |
| |
| # lua module |
| |
| The lua module is implemented in a file called libgem5OpLua.so, and should be |
| loaded using typical lua mechanisms. It will be built against lua 5.1. |
| |
| ## Integer values |
| |
| In lua 5.1, all numeric values are (typically) represented as doubles. That |
| means that 64 bit integer argument values of any type, but in particular |
| addresses, can't be represented exactly. Calls to gem5 operations using that |
| type of argument or returning that type of value may not work properly. |
| |
| In lua 5.3, numeric values can be represented by either a double or a proper |
| integer without having to rebuild the lua interpreter configured for one or the |
| other. If the module was ported to lua 5.3 then integer values could be passed |
| safely. |
| |
| |
| |
| # Known problems |
| |
| ## Java/lua cross compiling |
| |
| When building the java or lua modules, a C cross compiler is used so that any |
| generated binary will be built for the target ABI. Unfortunately, other tools, |
| headers, etc, come from the host and may not be useable, or worse may be |
| subtley broken, when used to target a different ABI. To build these objects |
| correctly, we would need to use a proper cross build environment for their |
| corresponding languages. Something like this could likely be set up using a |
| tool like buildroot. |
| |
| |