mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-13 20:12:26 +00:00
remove --gem5, use --emulator gem5 everywhere
Allow passing --emulator multiple times for transparent tests selection just like --arch.
This commit is contained in:
236
README.adoc
236
README.adoc
@ -342,7 +342,7 @@ If you haven't built Buildroot yet for <<qemu-buildroot-setup>>, you can build f
|
||||
|
||||
....
|
||||
./build --download-dependencies gem5-buildroot
|
||||
./run --gem5
|
||||
./run --emulator gem5
|
||||
....
|
||||
|
||||
If you have already built previously, don't be afraid: gem5 and QEMU use almost the same root filesystem and kernel, so `./build` will be fast.
|
||||
@ -364,7 +364,7 @@ You can quit the shell without killing gem5 by typing tilde followed by a period
|
||||
If you are inside <<tmux>>, which I highly recommend, you can both run gem5 stdout and open the guest terminal on a split window with:
|
||||
|
||||
....
|
||||
./run --gem5 --tmux
|
||||
./run --emulator gem5 --tmux
|
||||
....
|
||||
|
||||
See also: <<tmux-gem5>>.
|
||||
@ -381,7 +381,7 @@ but if you look closely, the `PS1` prompt marker `#` is there already, just hit
|
||||
If you forgot to open the shell and gem5 exit, you can inspect the terminal output post-mortem at:
|
||||
|
||||
....
|
||||
less "$(./getvar --gem5 m5out_dir)/system.pc.com_1.device"
|
||||
less "$(./getvar --emulator gem5 m5out_dir)/system.pc.com_1.device"
|
||||
....
|
||||
|
||||
More gem5 information is present at: <<gem5>>
|
||||
@ -570,7 +570,7 @@ For gem5, do:
|
||||
git submodule update --init --depth 1 "$(./getvar linux_source_dir)"
|
||||
sudo apt-get install qemu-utils
|
||||
./build-gem5
|
||||
./run --gem5 --prebuilt
|
||||
./run --emulator gem5 --prebuilt
|
||||
....
|
||||
|
||||
`qemu-utils` is required because we currently distribute `.qcow2` files which <<gem5-qcow2,gem5 can't handle>>, so we need `qemu-img` to extract them first.
|
||||
@ -783,7 +783,7 @@ To use gem5 instead of QEMU do:
|
||||
|
||||
....
|
||||
./build --download-dependencies gem5-baremetal
|
||||
./run --arch aarch64 --baremetal interactive/prompt --gem5
|
||||
./run --arch aarch64 --baremetal interactive/prompt --emulator gem5
|
||||
....
|
||||
|
||||
and then <<qemu-buildroot-setup,as usual>> open a shell with:
|
||||
@ -798,14 +798,14 @@ Note that `./build-baremetal` requires the `--gem5` option, and generates separa
|
||||
|
||||
....
|
||||
echo "$(./getvar --arch aarch64 --baremetal interactive/prompt image)"
|
||||
echo "$(./getvar --arch aarch64 --baremetal interactive/prompt --gem5 image)"
|
||||
echo "$(./getvar --arch aarch64 --baremetal interactive/prompt --emulator gem5 image)"
|
||||
....
|
||||
|
||||
This is unlike the Linux kernel that has a single image for both QEMU and gem5:
|
||||
|
||||
....
|
||||
echo "$(./getvar --arch aarch64 image)"
|
||||
echo "$(./getvar --arch aarch64 --gem5 image)"
|
||||
echo "$(./getvar --arch aarch64 --emulator gem5 image)"
|
||||
....
|
||||
|
||||
The reason for that is that on baremetal we don't parse the <<device-tree,device tress>> from memory like the Linux kernel does, which tells the kernel for example the UART address, and many other system parameters.
|
||||
@ -813,15 +813,15 @@ The reason for that is that on baremetal we don't parse the <<device-tree,device
|
||||
`gem5` also supports the `RealViewPBX` machine, which represents an older hardware compared to the default `VExpress_GEM5_V1`:
|
||||
|
||||
....
|
||||
./build-baremetal --arch aarch64 --gem5 --machine RealViewPBX
|
||||
./run --arch aarch64 --baremetal interactive/prompt --gem5 --machine RealViewPBX
|
||||
./build-baremetal --arch aarch64 --emulator gem5 --machine RealViewPBX
|
||||
./run --arch aarch64 --baremetal interactive/prompt --emulator gem5 --machine RealViewPBX
|
||||
....
|
||||
|
||||
This generates yet new separate images with new magic constants:
|
||||
|
||||
....
|
||||
echo "$(./getvar --arch aarch64 --baremetal interactive/prompt --gem5 --machine VExpress_GEM5_V1 image)"
|
||||
echo "$(./getvar --arch aarch64 --baremetal interactive/prompt --gem5 --machine RealViewPBX image)"
|
||||
echo "$(./getvar --arch aarch64 --baremetal interactive/prompt --emulator gem5 --machine VExpress_GEM5_V1 image)"
|
||||
echo "$(./getvar --arch aarch64 --baremetal interactive/prompt --emulator gem5 --machine RealViewPBX image)"
|
||||
....
|
||||
|
||||
But just stick to newer and better `VExpress_GEM5_V1` unless you have a good reason to use `RealViewPBX`.
|
||||
@ -990,7 +990,7 @@ Bibliography: https://unix.stackexchange.com/questions/152738/how-to-split-a-new
|
||||
If you are using gem5 instead of QEMU, `--tmux` has a different effect: it opens the gem5 terminal instead of the debugger:
|
||||
|
||||
....
|
||||
./run --gem5 --tmux
|
||||
./run --emulator gem5 --tmux
|
||||
....
|
||||
|
||||
If you also want to use the debugger with gem5, you will need to create new terminals as usual.
|
||||
@ -1001,7 +1001,7 @@ To see the debugger by default instead of the terminal, run:
|
||||
|
||||
....
|
||||
./tmu ./run-gdb
|
||||
./run --wait-gdb --gem5
|
||||
./run --wait-gdb --emulator gem5
|
||||
....
|
||||
|
||||
=== GDB step debug kernel module
|
||||
@ -3041,7 +3041,7 @@ So let's just play with some static ones:
|
||||
;
|
||||
./run \
|
||||
--arch aarch64 \
|
||||
--gem5 \
|
||||
--emulator gem5 \
|
||||
--userland print_argv \
|
||||
--userland-args 'asdf "qw er"' \
|
||||
;
|
||||
@ -3054,7 +3054,7 @@ Step debug also works:
|
||||
....
|
||||
./run \
|
||||
--arch aarch64 \
|
||||
--gem5 \
|
||||
--emulator gem5 \
|
||||
--userland print_argv \
|
||||
--userland-args 'asdf "qw er"' \
|
||||
--userland-build-id static \
|
||||
@ -3062,7 +3062,7 @@ Step debug also works:
|
||||
;
|
||||
./run-gdb \
|
||||
--arch aarch64 \
|
||||
--gem5 \
|
||||
--emulator gem5 \
|
||||
--userland print_argv \
|
||||
--userland-build-id static \
|
||||
main \
|
||||
@ -3074,7 +3074,7 @@ Step debug also works:
|
||||
As of gem5 7fa4c946386e7207ad5859e8ade0bbfc14000d91, the crappy `se.py` script does not forward the exit status of syscall emulation mode, you can test it with:
|
||||
|
||||
....
|
||||
./run --dry-run --gem5 --userland false --userland-build-id static
|
||||
./run --dry-run --emulator gem5 --userland false --userland-build-id static
|
||||
....
|
||||
|
||||
Source: link:userland/false[].
|
||||
@ -3112,7 +3112,7 @@ make \
|
||||
time \
|
||||
./run \
|
||||
--arch arm \
|
||||
--gem5 \
|
||||
--emulator gem5 \
|
||||
--userland "$(./getvar --arch arm buildroot_build_build_dir)/dhrystone-2/dhrystone" \
|
||||
--userland-args 'asdf qwer' \
|
||||
;
|
||||
@ -3125,7 +3125,7 @@ time \
|
||||
./run \
|
||||
--arch arm \
|
||||
--eval-after '/gem5.sh' \
|
||||
--gem5
|
||||
--emulator gem5
|
||||
--gem5-readfile 'dhrystone 100000' \
|
||||
;
|
||||
....
|
||||
@ -3158,9 +3158,9 @@ Result on <<p51>> at bad30f513c46c1b0995d3a10c0d9bc2a33dc4fa0:
|
||||
Automatically run non-interactive userland tests that don't depend on nay kernel modules:
|
||||
|
||||
....
|
||||
./build-userland --all-archs
|
||||
./build-userland --all-archs --static --userland-build-id static
|
||||
./test-userland --all-archs
|
||||
./build-userland --all-archs --all-emulators
|
||||
./build-userland --all-archs --all-emulators --static --userland-build-id static
|
||||
./test-userland --all-archs --all-emulators
|
||||
....
|
||||
|
||||
Source: link:test-userland[]
|
||||
@ -3547,7 +3547,7 @@ More concretely, first build the kernel with the <<gem5-arm-linux-kernel-patches
|
||||
--custom-config-file-gem5 \
|
||||
--linux-build-id gem5-v4.15 \
|
||||
;
|
||||
./run --arch arm --gem5 --linux-build-id gem5-v4.15
|
||||
./run --arch arm --emulator gem5 --linux-build-id gem5-v4.15
|
||||
....
|
||||
|
||||
and then on another shell:
|
||||
@ -3585,7 +3585,7 @@ Alternatively, you can also dump each new frame to an image file with `--frame-c
|
||||
....
|
||||
./run \
|
||||
--arch arm \
|
||||
--gem5 \
|
||||
--emulator gem5 \
|
||||
--linux-build-id gem5-v4.15 \
|
||||
-- --frame-capture \
|
||||
;
|
||||
@ -3623,7 +3623,7 @@ git -C "$(./getvar linux_source_dir)" checkout gem5/v4.15
|
||||
--linux-build-id gem5-v4.15 \
|
||||
;
|
||||
git -C "$(./getvar linux_source_dir)" checkout -
|
||||
./run --arch aarch64 --gem5 --linux-build-id gem5-v4.15
|
||||
./run --arch aarch64 --emulator gem5 --linux-build-id gem5-v4.15
|
||||
....
|
||||
|
||||
This is because the gem5 `aarch64` defconfig does not enable HDLCD like the 32 bit one `arm` one for some reason.
|
||||
@ -3639,7 +3639,7 @@ The key option to enable support in Linux is `DRM_MALI_DISPLAY=y` which we enabl
|
||||
Build the kernel exactly as for <<graphic-mode-gem5-aarch64>> and then run with:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --dp650 --gem5 --linux-build-id gem5-v4.15
|
||||
./run --arch aarch64 --dp650 --emulator gem5 --linux-build-id gem5-v4.15
|
||||
....
|
||||
|
||||
==== Graphic mode gem5 internals
|
||||
@ -6733,9 +6733,9 @@ instructions_firmware 20708
|
||||
gem5:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --gem5 --eval 'm5 exit'
|
||||
./run --arch aarch64 --emulator gem5 --eval 'm5 exit'
|
||||
# Or:
|
||||
# ./run --arch aarch64 --gem5 --eval 'm5 exit' -- --cpu-type=HPI --caches
|
||||
# ./run --arch aarch64 --emulator gem5 --eval 'm5 exit' -- --cpu-type=HPI --caches
|
||||
./gem5-stat --arch aarch64 sim_insts
|
||||
....
|
||||
|
||||
@ -8281,7 +8281,7 @@ You can still send key presses to QEMU however even without the mouse capture, j
|
||||
Start pdb at the first instruction:
|
||||
|
||||
....
|
||||
./run --gem5 --gem5-exe-args='--pdb' --terminal
|
||||
./run --emulator gem5 --gem5-exe-args='--pdb' --terminal
|
||||
....
|
||||
|
||||
Requires `--terminal` as we must be on foreground.
|
||||
@ -8295,7 +8295,7 @@ import ipdb; ipdb.set_trace()
|
||||
and then run with:
|
||||
|
||||
....
|
||||
./run --gem5 --terminal
|
||||
./run --emulator gem5 --terminal
|
||||
....
|
||||
|
||||
TODO test PyCharm: https://stackoverflow.com/questions/51982735/writing-gem5-configuration-scripts-with-pycharm
|
||||
@ -8565,14 +8565,14 @@ just appears to output both cores intertwined without any clear differentiation.
|
||||
gem5 provides also provides a tracing mechanism documented at: link:http://www.gem5.org/Trace_Based_Debugging[]:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --eval 'm5 exit' --gem5 --trace Exec
|
||||
./run --arch aarch64 --eval 'm5 exit' --emulator gem5 --trace Exec
|
||||
less "$(./getvar --arch aarch64 run_dir)/trace.txt"
|
||||
....
|
||||
|
||||
Output the trace to stdout instead of a file:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --eval 'm5 exit' --gem5 --trace Exec --trace-stdout
|
||||
./run --arch aarch64 --eval 'm5 exit' --emulator gem5 --trace Exec --trace-stdout
|
||||
....
|
||||
|
||||
This would produce a lot of output however, so you will likely not want that when tracing a Linux kernel boot instructions. But it can be very convenient for smaller traces.
|
||||
@ -8580,7 +8580,7 @@ This would produce a lot of output however, so you will likely not want that whe
|
||||
List all available debug flags:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --gem5-exe-args='--debug-help' --gem5
|
||||
./run --arch aarch64 --gem5-exe-args='--debug-help' --emulator gem5
|
||||
....
|
||||
|
||||
but to understand most of them you have to look at the source code:
|
||||
@ -8633,8 +8633,8 @@ The best way to verify all of this is to write some <<baremetal,baremetal code>>
|
||||
Trace the source lines just like <<trace-source-lines,for QEMU>> with:
|
||||
|
||||
....
|
||||
./trace-boot --arch aarch64 --gem5
|
||||
./trace2line --arch aarch64 --gem5
|
||||
./trace-boot --arch aarch64 --emulator gem5
|
||||
./trace2line --arch aarch64 --emulator gem5
|
||||
less "$(./getvar --arch aarch64 run_dir)/trace-lines.txt"
|
||||
....
|
||||
|
||||
@ -8743,7 +8743,7 @@ Another interesting example can be found at: link:gem5-bench-cache[].
|
||||
A more naive and simpler to understand approach would be a direct:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --gem5 --eval 'm5 checkpoint;m5 resetstats;dhrystone 10000;m5 exit'
|
||||
./run --arch aarch64 --emulator gem5 --eval 'm5 checkpoint;m5 resetstats;dhrystone 10000;m5 exit'
|
||||
....
|
||||
|
||||
but the problem is that this method does not allow to easily run a different script without running the boot again, see: <<gem5-restore-new-script>>.
|
||||
@ -8781,7 +8781,7 @@ The rabbit hole is likely deep, but let's scratch a bit of the surface.
|
||||
===== Number of cores
|
||||
|
||||
....
|
||||
./run --arch arm --cpus 2 --gem5
|
||||
./run --arch arm --cpus 2 --emulator gem5
|
||||
....
|
||||
|
||||
Check with:
|
||||
@ -8801,7 +8801,7 @@ Build the kernel with the <<gem5-arm-linux-kernel-patches>>, and then run:
|
||||
./run \
|
||||
--arch aarch64 \
|
||||
--linux-build-id gem5-v4.15 \
|
||||
--gem5 \
|
||||
--emulator gem5 \
|
||||
--cpus 16 \
|
||||
-- \
|
||||
--param 'system.realview.gic.gem5_extensions = True' \
|
||||
@ -8812,7 +8812,7 @@ Build the kernel with the <<gem5-arm-linux-kernel-patches>>, and then run:
|
||||
|
||||
https://stackoverflow.com/questions/49624061/how-to-run-gem5-simulator-in-fs-mode-without-cache/49634544#49634544
|
||||
|
||||
A quick `+./run --gem5 -- -h+` leads us to the options:
|
||||
A quick `+./run --emulator gem5 -- -h+` leads us to the options:
|
||||
|
||||
....
|
||||
--caches
|
||||
@ -8879,37 +8879,37 @@ cat "$(./getvar --arch aarch64 run_dir)/bench-cache.txt"
|
||||
which gives:
|
||||
|
||||
....
|
||||
cmd ./run --gem5 --arch aarch64 --gem5-readfile "dhrystone 1000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024 --l1i_size=1024 --l2_size=1024 --l3_size=1024 --cpu-type=HPI --restore-with-cpu=HPI
|
||||
cmd ./run --emulator gem5 --arch aarch64 --gem5-readfile "dhrystone 1000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024 --l1i_size=1024 --l2_size=1024 --l3_size=1024 --cpu-type=HPI --restore-with-cpu=HPI
|
||||
time 23.82
|
||||
exit_status 0
|
||||
cycles 93284622
|
||||
instructions 4393457
|
||||
|
||||
cmd ./run --gem5 --arch aarch64 --gem5-readfile "dhrystone 1000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB --cpu-type=HPI --restore-with-cpu=HPI
|
||||
cmd ./run --emulator gem5 --arch aarch64 --gem5-readfile "dhrystone 1000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB --cpu-type=HPI --restore-with-cpu=HPI
|
||||
time 14.91
|
||||
exit_status 0
|
||||
cycles 10128985
|
||||
instructions 4211458
|
||||
|
||||
cmd ./run --gem5 --arch aarch64 --gem5-readfile "dhrystone 10000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024 --l1i_size=1024 --l2_size=1024 --l3_size=1024 --cpu-type=HPI --restore-with-cpu=HPI
|
||||
cmd ./run --emulator gem5 --arch aarch64 --gem5-readfile "dhrystone 10000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024 --l1i_size=1024 --l2_size=1024 --l3_size=1024 --cpu-type=HPI --restore-with-cpu=HPI
|
||||
time 51.87
|
||||
exit_status 0
|
||||
cycles 188803630
|
||||
instructions 12401336
|
||||
|
||||
cmd ./run --gem5 --arch aarch64 --gem5-readfile "dhrystone 10000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB --cpu-type=HPI --restore-with-cpu=HPI
|
||||
cmd ./run --emulator gem5 --arch aarch64 --gem5-readfile "dhrystone 10000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB --cpu-type=HPI --restore-with-cpu=HPI
|
||||
time 35.35
|
||||
exit_status 0
|
||||
cycles 20715757
|
||||
instructions 12192527
|
||||
|
||||
cmd ./run --gem5 --arch aarch64 --gem5-readfile "dhrystone 100000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024 --l1i_size=1024 --l2_size=1024 --l3_size=1024 --cpu-type=HPI --restore-with-cpu=HPI
|
||||
cmd ./run --emulator gem5 --arch aarch64 --gem5-readfile "dhrystone 100000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024 --l1i_size=1024 --l2_size=1024 --l3_size=1024 --cpu-type=HPI --restore-with-cpu=HPI
|
||||
time 339.07
|
||||
exit_status 0
|
||||
cycles 1176559936
|
||||
instructions 94222791
|
||||
|
||||
cmd ./run --gem5 --arch aarch64 --gem5-readfile "dhrystone 100000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB --cpu-type=HPI --restore-with-cpu=HPI
|
||||
cmd ./run --emulator gem5 --arch aarch64 --gem5-readfile "dhrystone 100000" --gem5-restore 1 -- --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB --cpu-type=HPI --restore-with-cpu=HPI
|
||||
time 240.37
|
||||
exit_status 0
|
||||
cycles 125666679
|
||||
@ -8963,7 +8963,7 @@ and also: `gem5-dist`: https://publish.illinois.edu/icsl-pdgem5/
|
||||
Clock frequency: TODO how does it affect performance in benchmarks?
|
||||
|
||||
....
|
||||
./run --arch aarch64 --gem5 -- --cpu-clock 10000000
|
||||
./run --arch aarch64 --emulator gem5 -- --cpu-clock 10000000
|
||||
....
|
||||
|
||||
Check with:
|
||||
@ -9011,10 +9011,10 @@ Usage:
|
||||
./run \
|
||||
--arch aarch64 \
|
||||
--eval-after '/gem5.sh' \
|
||||
--gem5 \
|
||||
--emulator gem5 \
|
||||
--gem5-readfile '/bst_vs_heap.out' \
|
||||
;
|
||||
./bst-vs-heap --arch aarch64 --gem5 > bst_vs_heap.dat
|
||||
./bst-vs-heap --arch aarch64 --emulator gem5 > bst_vs_heap.dat
|
||||
....
|
||||
|
||||
and then feed `bst_vs_heap.dat` into: https://github.com/cirosantilli/cpp-cheat/blob/9d0f77792fc8e55b20b6ee32018761ef3c5a3f2f/cpp/interactive/bst_vs_heap.gnuplot
|
||||
@ -9116,7 +9116,7 @@ There are two ways to run PARSEC with this repo:
|
||||
....
|
||||
./build --arch arm --download-dependencies gem5-buildroot parsec-benchmark
|
||||
./build-buildroot --arch arm --config 'BR2_PACKAGE_PARSEC_BENCHMARK=y'
|
||||
./run --arch arm --gem5
|
||||
./run --arch arm --emulator gem5
|
||||
....
|
||||
|
||||
Once inside the guest, launch one of the `test` input sized benchmarks manually as in:
|
||||
@ -9270,7 +9270,7 @@ You may also want to test if your patches are still functionally correct inside
|
||||
Analogous <<kernel-command-line-parameters,to QEMU>>:
|
||||
|
||||
....
|
||||
./run --arch arm --kernel-cli 'init=/poweroff.out' --gem5
|
||||
./run --arch arm --kernel-cli 'init=/poweroff.out' --emulator gem5
|
||||
....
|
||||
|
||||
Internals: when we give `--command-line=` to gem5, it overrides default command lines, including some mandatory ones which are required to boot properly.
|
||||
@ -9280,7 +9280,7 @@ Our run script hardcodes the require options in the default `--command-line` and
|
||||
To find the default options in the first place, we removed `--command-line` and ran:
|
||||
|
||||
....
|
||||
./run --arch arm --gem5
|
||||
./run --arch arm --emulator gem5
|
||||
....
|
||||
|
||||
and then looked at the line of the Linux kernel that starts with:
|
||||
@ -9296,13 +9296,13 @@ Kernel command line:
|
||||
Analogous <<gdb,to QEMU>>, on the first shell:
|
||||
|
||||
....
|
||||
./run --arch arm --wait-gdb --gem5
|
||||
./run --arch arm --wait-gdb --emulator gem5
|
||||
....
|
||||
|
||||
On the second shell:
|
||||
|
||||
....
|
||||
./run-gdb --arch arm --gem5
|
||||
./run-gdb --arch arm --emulator gem5
|
||||
....
|
||||
|
||||
On a third shell:
|
||||
@ -9335,7 +9335,7 @@ I press `n`, it just runs the program until the end, instead of stopping on the
|
||||
TODO:
|
||||
|
||||
....
|
||||
./run-gdb-user --arch arm --gem5 gem5-1.0/gem5/util/m5/m5 main
|
||||
./run-gdb-user --arch arm --emulator gem5 gem5-1.0/gem5/util/m5/m5 main
|
||||
....
|
||||
|
||||
breaks when `m5` is run on guest, but does not show the source code.
|
||||
@ -9347,7 +9347,7 @@ Analogous to QEMU's <<snapshot>>, but better since it can be started from inside
|
||||
Documentation: http://gem5.org/Checkpoints
|
||||
|
||||
....
|
||||
./run --arch arm --gem5
|
||||
./run --arch arm --emulator gem5
|
||||
....
|
||||
|
||||
In the guest, wait for the boot to end and run:
|
||||
@ -9361,7 +9361,7 @@ where <<m5>> is a guest utility present inside the gem5 tree which we cross-comp
|
||||
To restore the checkpoint, kill the VM and run:
|
||||
|
||||
....
|
||||
./run --arch arm --gem5 --gem5-restore 1
|
||||
./run --arch arm --emulator gem5 --gem5-restore 1
|
||||
....
|
||||
|
||||
The `--gem5-restore` option restores the checkpoint that was created most recently.
|
||||
@ -9376,7 +9376,7 @@ m5 checkpoint
|
||||
Kill the VM, and try it out:
|
||||
|
||||
....
|
||||
./run --arch arm --gem5 --gem5-restore 1
|
||||
./run --arch arm --emulator gem5 --gem5-restore 1
|
||||
....
|
||||
|
||||
Here we use `--gem5-restore 1` again, since the second snapshot we took is now the most recent one
|
||||
@ -9392,13 +9392,13 @@ contains the `date`. The file `f` wouldn't exist had we used the first checkpoin
|
||||
If you automate things with <<kernel-command-line-parameters>> as in:
|
||||
|
||||
....
|
||||
./run --arch arm --eval 'm5 checkpoint;m5 resetstats;dhrystone 1000;m5 exit' --gem5
|
||||
./run --arch arm --eval 'm5 checkpoint;m5 resetstats;dhrystone 1000;m5 exit' --emulator gem5
|
||||
....
|
||||
|
||||
Then there is no need to pass the kernel command line again to gem5 for replay:
|
||||
|
||||
....
|
||||
./run --arch arm --gem5 --gem5-restore 1
|
||||
./run --arch arm --emulator gem5 --gem5-restore 1
|
||||
....
|
||||
|
||||
since boot has already happened, and the parameters are already in the RAM of the snapshot.
|
||||
@ -9408,7 +9408,7 @@ since boot has already happened, and the parameters are already in the RAM of th
|
||||
Checkpoints are stored inside the <<m5out-directory>> at:
|
||||
|
||||
....
|
||||
"$(./getvar --gem5 m5out_dir)/cpt.<checkpoint-time>"
|
||||
"$(./getvar --emulator gem5 m5out_dir)/cpt.<checkpoint-time>"
|
||||
....
|
||||
|
||||
where `<checkpoint-time>` is the cycle number at which the checkpoint was taken.
|
||||
@ -9438,19 +9438,19 @@ So we can do it like:
|
||||
....
|
||||
# Boot, checkpoint and exit.
|
||||
printf 'echo "setup run";m5 exit' > "$(./getvar gem5_readfile)"
|
||||
./run --gem5 --eval 'm5 checkpoint;m5 readfile > a.sh;sh a.sh'
|
||||
./run --emulator gem5 --eval 'm5 checkpoint;m5 readfile > a.sh;sh a.sh'
|
||||
|
||||
# Restore and run the first benchmark.
|
||||
printf 'echo "first benchmark";m5 exit' > "$(./getvar gem5_readfile)"
|
||||
./run --gem5 --gem5-restore 1
|
||||
./run --emulator gem5 --gem5-restore 1
|
||||
|
||||
# Restore and run the second benchmark.
|
||||
printf 'echo "second benchmark";m5 exit' > "$(./getvar gem5_readfile)"
|
||||
./run --gem5 --gem5-restore 1
|
||||
./run --emulator gem5 --gem5-restore 1
|
||||
|
||||
# If something weird happened, create an interactive shell to examine the system.
|
||||
printf 'sh' > "$(./getvar gem5_readfile)"
|
||||
./run --gem5 --gem5-restore 1
|
||||
./run --emulator gem5 --gem5-restore 1
|
||||
....
|
||||
|
||||
Since this is such a common setup, we provide some helpers for it as described at <<gem5-run-benchmark>>:
|
||||
@ -9487,7 +9487,7 @@ A common combo is to boot Linux with a fast CPU, make a checkpoint and then repl
|
||||
An illustrative interactive run:
|
||||
|
||||
....
|
||||
./run --arch arm --gem5
|
||||
./run --arch arm --emulator gem5
|
||||
....
|
||||
|
||||
In guest:
|
||||
@ -9499,7 +9499,7 @@ m5 checkpoint
|
||||
And then restore the checkpoint with a different CPU:
|
||||
|
||||
....
|
||||
./run --arch arm --gem5 --gem5-restore 1 -- --caches --restore-with-cpu=HPI
|
||||
./run --arch arm --emulator gem5 --gem5-restore 1 -- --caches --restore-with-cpu=HPI
|
||||
....
|
||||
|
||||
=== Pass extra options to gem5
|
||||
@ -9509,12 +9509,12 @@ Pass options to the `fs.py` script:
|
||||
* get help:
|
||||
+
|
||||
....
|
||||
./run --gem5 -- -h
|
||||
./run --emulator gem5 -- -h
|
||||
....
|
||||
* boot with the more detailed and slow `HPI` CPU model:
|
||||
+
|
||||
....
|
||||
./run --arch arm --gem5 -- --caches --cpu-type=HPI
|
||||
./run --arch arm --emulator gem5 -- --caches --cpu-type=HPI
|
||||
....
|
||||
|
||||
Pass options to the `gem5` executable itself:
|
||||
@ -9522,7 +9522,7 @@ Pass options to the `gem5` executable itself:
|
||||
* get help:
|
||||
+
|
||||
....
|
||||
./run --gem5-exe-args='-h' --gem5
|
||||
./run --gem5-exe-args='-h' --emulator gem5
|
||||
....
|
||||
|
||||
=== gem5 exit after a number of instructions
|
||||
@ -9530,7 +9530,7 @@ Pass options to the `gem5` executable itself:
|
||||
Quit the simulation after `1024` instructions:
|
||||
|
||||
....
|
||||
./run --gem5 -- -I 1024
|
||||
./run --emulator gem5 -- -I 1024
|
||||
....
|
||||
|
||||
Can be nicely checked with <<gem5-tracing>>.
|
||||
@ -9538,7 +9538,7 @@ Can be nicely checked with <<gem5-tracing>>.
|
||||
Cycles instead of instructions:
|
||||
|
||||
....
|
||||
./run --gem5 -- --memory 1024
|
||||
./run --emulator gem5 -- --memory 1024
|
||||
....
|
||||
|
||||
Otherwise the simulation runs forever by default.
|
||||
@ -9619,7 +9619,7 @@ m5 writefile myfileguest myfilehost
|
||||
Host:
|
||||
|
||||
....
|
||||
cat "$(./getvar --arch aarch64 --gem5 m5out_dir)/myfilehost"
|
||||
cat "$(./getvar --arch aarch64 --emulator gem5 m5out_dir)/myfilehost"
|
||||
....
|
||||
|
||||
Does not work for subdirectories, gem5 crashes:
|
||||
@ -9655,8 +9655,8 @@ Ermm, just another <<m5-readfile>> that only takes integers and only from CLI op
|
||||
Host:
|
||||
|
||||
....
|
||||
./run --gem5 --gem5-restore 1 -- --initparam 13
|
||||
./run --gem5 --gem5-restore 1 -- --initparam 42
|
||||
./run --emulator gem5 --gem5-restore 1 -- --initparam 13
|
||||
./run --emulator gem5 --gem5-restore 1 -- --initparam 42
|
||||
....
|
||||
|
||||
Guest:
|
||||
@ -9831,7 +9831,7 @@ It is obviously not possible to understand what they actually do from their comm
|
||||
When you run gem5, it generates an `m5out` directory at:
|
||||
|
||||
....
|
||||
echo $(./getvar --arch arm --gem5 m5out_dir)"
|
||||
echo $(./getvar --arch arm --emulator gem5 m5out_dir)"
|
||||
....
|
||||
|
||||
The location of that directory can be set with `./gem5.opt -d`, and defaults to `./m5out`.
|
||||
@ -9874,7 +9874,7 @@ Let's have some fun and try to correlate the gem5 cycle count `system.cpu.numCyc
|
||||
|
||||
....
|
||||
./build-userland -- rdtsc
|
||||
./run --eval '/rdtsc.out;m5 exit;' --gem5
|
||||
./run --eval '/rdtsc.out;m5 exit;' --emulator gem5
|
||||
./gem5-stat
|
||||
....
|
||||
|
||||
@ -9907,7 +9907,7 @@ TODO We didn't manage to find a working ARM analogue to <<rdtsc>>: link:kernel_m
|
||||
The `config.ini` file, contains a very good high level description of the system:
|
||||
|
||||
....
|
||||
less $(./getvar --arch arm --gem5 m5out_dir)"
|
||||
less $(./getvar --arch arm --emulator gem5 m5out_dir)"
|
||||
....
|
||||
|
||||
That file contains a tree representation of the system, sample excerpt:
|
||||
@ -9945,7 +9945,7 @@ For example, `AtomicSimpleCPU` maps is defined at link:https://github.com/gem5/g
|
||||
You can also get a simplified graphical view of the tree with:
|
||||
|
||||
....
|
||||
xdg-open "$(./getvar --arch arm --gem5 m5out_dir)/config.dot.pdf"
|
||||
xdg-open "$(./getvar --arch arm --emulator gem5 m5out_dir)/config.dot.pdf"
|
||||
....
|
||||
|
||||
Modifying the `config.ini` file manually does nothing since it gets overwritten every time.
|
||||
@ -10004,7 +10004,7 @@ patch -d "$(./getvar gem5_source_dir)" -p 1 < patches/manual/gem5-biglittle.patc
|
||||
then:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --gem5 --gem5-script biglittle
|
||||
./run --arch aarch64 --emulator gem5 --gem5-script biglittle
|
||||
....
|
||||
|
||||
Advantages over `fs.py`:
|
||||
@ -10632,18 +10632,18 @@ TODO: why is `arm` stuck at `19` which equals Supervisor mode?
|
||||
In gem5, you can configure the lowest EL with:
|
||||
|
||||
....
|
||||
./run --arch arm --baremetal arch/arm/el --gem5
|
||||
cat "$(./getvar --arch arm --gem5 gem5_guest_terminal_file)"
|
||||
./run --arch arm --baremetal arch/arm/el --gem5 -- --param 'system.have_virtualization = True'
|
||||
cat "$(./getvar --arch arm --gem5 gem5_guest_terminal_file)"
|
||||
./run --arch arm --baremetal arch/arm/el --gem5 -- --param 'system.have_security = True'
|
||||
cat "$(./getvar --arch arm --gem5 gem5_guest_terminal_file)"
|
||||
./run --arch aarch64 --baremetal arch/aarch64/el --gem5
|
||||
cat "$(./getvar --arch aarch64 --gem5 gem5_guest_terminal_file)"
|
||||
./run --arch aarch64 --baremetal arch/aarch64/el --gem5 -- --param 'system.have_virtualization = True'
|
||||
cat "$(./getvar --arch aarch64 --gem5 gem5_guest_terminal_file)"
|
||||
./run --arch aarch64 --baremetal arch/aarch64/el --gem5 -- --param 'system.have_security = True'
|
||||
cat "$(./getvar --arch aarch64 --gem5 gem5_guest_terminal_file)"
|
||||
./run --arch arm --baremetal arch/arm/el --emulator gem5
|
||||
cat "$(./getvar --arch arm --emulator gem5 gem5_guest_terminal_file)"
|
||||
./run --arch arm --baremetal arch/arm/el --emulator gem5 -- --param 'system.have_virtualization = True'
|
||||
cat "$(./getvar --arch arm --emulator gem5 gem5_guest_terminal_file)"
|
||||
./run --arch arm --baremetal arch/arm/el --emulator gem5 -- --param 'system.have_security = True'
|
||||
cat "$(./getvar --arch arm --emulator gem5 gem5_guest_terminal_file)"
|
||||
./run --arch aarch64 --baremetal arch/aarch64/el --emulator gem5
|
||||
cat "$(./getvar --arch aarch64 --emulator gem5 gem5_guest_terminal_file)"
|
||||
./run --arch aarch64 --baremetal arch/aarch64/el --emulator gem5 -- --param 'system.have_virtualization = True'
|
||||
cat "$(./getvar --arch aarch64 --emulator gem5 gem5_guest_terminal_file)"
|
||||
./run --arch aarch64 --baremetal arch/aarch64/el --emulator gem5 -- --param 'system.have_security = True'
|
||||
cat "$(./getvar --arch aarch64 --emulator gem5 gem5_guest_terminal_file)"
|
||||
....
|
||||
|
||||
output:
|
||||
@ -10661,9 +10661,9 @@ output:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --baremetal arch/aarch64/multicore --cpus 2
|
||||
./run --arch aarch64 --baremetal arch/aarch64/multicore --cpus 2 --gem5
|
||||
./run --arch aarch64 --baremetal arch/aarch64/multicore --cpus 2 --emulator gem5
|
||||
./run --arch arm --baremetal arch/aarch64/multicore --cpus 2
|
||||
./run --arch arm --baremetal arch/aarch64/multicore --cpus 2 --gem5
|
||||
./run --arch arm --baremetal arch/aarch64/multicore --cpus 2 --emulator gem5
|
||||
....
|
||||
|
||||
Sources:
|
||||
@ -10686,7 +10686,7 @@ and watch it hang forever.
|
||||
Note that if you try the same thing on gem5:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --baremetal arch/aarch64/multicore --cpus 1 --gem5
|
||||
./run --arch aarch64 --baremetal arch/aarch64/multicore --cpus 1 --emulator gem5
|
||||
....
|
||||
|
||||
then the gem5 actually exits, but with a different message:
|
||||
@ -10977,7 +10977,7 @@ time 8.83
|
||||
exit_status 0
|
||||
instructions 2244297
|
||||
|
||||
cmd ./run --arch x86_64 --eval 'm5 exit' --gem5
|
||||
cmd ./run --arch x86_64 --eval 'm5 exit' --emulator gem5
|
||||
time 213.39
|
||||
exit_status 0
|
||||
instructions 318486337
|
||||
@ -10990,12 +10990,12 @@ time 6.90
|
||||
exit_status 0
|
||||
instructions 776374
|
||||
|
||||
cmd ./run --arch arm --eval 'm5 exit' --gem5
|
||||
cmd ./run --arch arm --eval 'm5 exit' --emulator gem5
|
||||
time 118.46
|
||||
exit_status 0
|
||||
instructions 153023392
|
||||
|
||||
cmd ./run --arch arm --eval 'm5 exit' --gem5 -- --cpu-type=HPI --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB
|
||||
cmd ./run --arch arm --eval 'm5 exit' --emulator gem5 -- --cpu-type=HPI --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB
|
||||
time 2250.40
|
||||
exit_status 0
|
||||
instructions 151981914
|
||||
@ -11009,22 +11009,22 @@ time 5.04
|
||||
exit_status 0
|
||||
instructions 233162
|
||||
|
||||
cmd ./run --arch aarch64 --eval 'm5 exit' --gem5
|
||||
cmd ./run --arch aarch64 --eval 'm5 exit' --emulator gem5
|
||||
time 70.89
|
||||
exit_status 0
|
||||
instructions 124346081
|
||||
|
||||
cmd ./run --arch aarch64 --eval 'm5 exit' --gem5 -- --cpu-type=HPI --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB
|
||||
cmd ./run --arch aarch64 --eval 'm5 exit' --emulator gem5 -- --cpu-type=HPI --caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB
|
||||
time 381.86
|
||||
exit_status 0
|
||||
instructions 124564620
|
||||
|
||||
cmd ./run --arch aarch64 --eval 'm5 exit' --gem5 --gem5-build-type fast
|
||||
cmd ./run --arch aarch64 --eval 'm5 exit' --emulator gem5 --gem5-build-type fast
|
||||
time 58.00
|
||||
exit_status 0
|
||||
instructions 124346081
|
||||
|
||||
cmd ./run --arch aarch64 --eval 'm5 exit' --gem5 --gem5-build-type debug
|
||||
cmd ./run --arch aarch64 --eval 'm5 exit' --emulator gem5 --gem5-build-type debug
|
||||
time 1022.03
|
||||
exit_status 0
|
||||
instructions 124346081
|
||||
@ -11037,7 +11037,7 @@ TODO: aarch64 gem5 and QEMU use the same kernel, so why is the gem5 instruction
|
||||
TODO 62f6870e4e0b384c4bd2d514116247e81b241251 takes 33 minutes to finish at 62f6870e4e0b384c4bd2d514116247e81b241251:
|
||||
|
||||
....
|
||||
cmd ./run --arch arm --eval 'm5 exit' --gem5 -- --caches --cpu-type=HPI
|
||||
cmd ./run --arch arm --eval 'm5 exit' --emulator gem5 -- --caches --cpu-type=HPI
|
||||
....
|
||||
|
||||
while aarch64 only 7 minutes.
|
||||
@ -11138,7 +11138,7 @@ Sample results at gem5 2a9573f5942b5416fb0570cf5cb6cdecba733392: 10 to 12 minute
|
||||
Get results with:
|
||||
|
||||
....
|
||||
./bench-all --gem5
|
||||
./bench-all --emulator gem5
|
||||
tail -n+1 ../linux-kernel-module-cheat-regression/*/gem5-bench-build-*.txt
|
||||
....
|
||||
|
||||
@ -11420,22 +11420,22 @@ Our scripts solve two difficulties with simultaneous runs:
|
||||
Each run gets a separate output directory. For example:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --gem5 --run-id 0 &>/dev/null &
|
||||
./run --arch aarch64 --gem5 --run-id 1 &>/dev/null &
|
||||
./run --arch aarch64 --emulator gem5 --run-id 0 &>/dev/null &
|
||||
./run --arch aarch64 --emulator gem5 --run-id 1 &>/dev/null &
|
||||
....
|
||||
|
||||
produces two separate <<m5out-directory,`m5out` directories>>:
|
||||
|
||||
....
|
||||
echo "$(./getvar --arch aarch64 --gem5 --run-id 0 m5out_dir)"
|
||||
echo "$(./getvar --arch aarch64 --gem5 --run-id 1 m5out_dir)"
|
||||
echo "$(./getvar --arch aarch64 --emulator gem5 --run-id 0 m5out_dir)"
|
||||
echo "$(./getvar --arch aarch64 --emulator gem5 --run-id 1 m5out_dir)"
|
||||
....
|
||||
|
||||
and the gem5 host executable stdout and stderr can be found at:
|
||||
|
||||
....
|
||||
less "$(./getvar --arch aarch64 --gem5 --run-id 0 termout_file)"
|
||||
less "$(./getvar --arch aarch64 --gem5 --run-id 1 termout_file)"
|
||||
less "$(./getvar --arch aarch64 --emulator gem5 --run-id 0 termout_file)"
|
||||
less "$(./getvar --arch aarch64 --emulator gem5 --run-id 1 termout_file)"
|
||||
....
|
||||
|
||||
Each line is prepended with the timestamp in seconds since the start of the program when it appeared.
|
||||
@ -11443,7 +11443,7 @@ Each line is prepended with the timestamp in seconds since the start of the prog
|
||||
To have more semantic output directories names for later inspection, you can use a non numeric string for the run ID, and indicate the port offset explicitly:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --gem5 --run-id some-experiment --port-offset 1
|
||||
./run --arch aarch64 --emulator gem5 --run-id some-experiment --port-offset 1
|
||||
....
|
||||
|
||||
`--port-offset` defaults to the run ID when that is a number.
|
||||
@ -11540,11 +11540,11 @@ git -C "$(./getvar gem5_source_dir)" checkout some-branch
|
||||
git -C "$(./getvar gem5_source_dir)" checkout -
|
||||
|
||||
# Run master.
|
||||
./run --gem5
|
||||
./run --emulator gem5
|
||||
|
||||
# Run another branch.
|
||||
git -C "$(./getvar gem5_source_dir)" checkout some-branch
|
||||
./run --gem5-build-id some-branch --gem5
|
||||
./run --gem5-build-id some-branch --emulator gem5
|
||||
....
|
||||
|
||||
Don't forget however that gem5 has Python scripts in its source code tree, and that those must match the source code of a given build.
|
||||
@ -11569,11 +11569,11 @@ cd -
|
||||
./build-gem5 --gem5-worktree my-new-feature
|
||||
|
||||
# Run the submodule.
|
||||
./run --gem5 --run-id 0 &>/dev/null &
|
||||
./run --emulator gem5 --run-id 0 &>/dev/null &
|
||||
|
||||
# Run the branch the need to check out anything.
|
||||
# With --gem5-worktree, we can do both runs at the same time!
|
||||
./run --gem5 --gem5-worktree my-new-feature --run-id 1 &>/dev/null &
|
||||
./run --emulator gem5 --gem5-worktree my-new-feature --run-id 1 &>/dev/null &
|
||||
....
|
||||
|
||||
`--gem5-worktree <worktree-id>` automatically creates:
|
||||
@ -11628,7 +11628,7 @@ The `gem5.debug` executable has optimizations turned off unlike the default `gem
|
||||
|
||||
....
|
||||
./build-gem5 --arch aarch64 --gem5-build-type debug
|
||||
./run --arch aarch64 --debug-vm --gem5 --gem5-build-type debug
|
||||
./run --arch aarch64 --debug-vm --emulator gem5 --gem5-build-type debug
|
||||
....
|
||||
|
||||
The build outputs are automatically stored in a different directory from other build types such as `.opt` build, which prevents `.debug` files from overwriting `.opt` ones.
|
||||
@ -11638,8 +11638,8 @@ Therefore, `--gem5-build-id` is not required.
|
||||
The price to pay for debuggability is high however: a Linux kernel boot was about 14 times slower than opt at 71e927e63bda6507d5a528f22c78d65099bdf36f between the commands:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --eval 'm5 exit' --gem5 --linux-build-id v4.16
|
||||
./run --arch aarch64 --eval 'm5 exit' --gem5 --linux-build-id v4.16 --gem5-build-type debug
|
||||
./run --arch aarch64 --eval 'm5 exit' --emulator gem5 --linux-build-id v4.16
|
||||
./run --arch aarch64 --eval 'm5 exit' --emulator gem5 --linux-build-id v4.16 --gem5-build-type debug
|
||||
....
|
||||
|
||||
so you will likely only use this when it is unavoidable.
|
||||
@ -11884,7 +11884,7 @@ We have some link:https://github.com/pexpect/pexpect[pexpect] automated tests fo
|
||||
|
||||
....
|
||||
./build-test-gdb && \
|
||||
./test-gdb --all-archs
|
||||
./test-gdb --all-archs --all-emulators
|
||||
....
|
||||
|
||||
Sources:
|
||||
|
||||
12
bench-boot
12
bench-boot
@ -57,7 +57,7 @@ if [ "$test_size" -ge 2 ]; then
|
||||
bench "$arch --eval 'm5 exit' --gem5"
|
||||
gem5_insts "$arch"
|
||||
fi
|
||||
#bench "$arch --eval 'm5 exit' --gem5 -- --cpu-type=DerivO3CPU ${caches}"
|
||||
#bench "$arch --eval 'm5 exit' --emulator gem5 -- --cpu-type=DerivO3CPU ${caches}"
|
||||
#gem5_insts "$arch"
|
||||
|
||||
arch=arm
|
||||
@ -69,7 +69,7 @@ if [ "$test_size" -ge 2 ]; then
|
||||
gem5_insts "$arch"
|
||||
fi
|
||||
if [ "$test_size" -ge 3 ]; then
|
||||
bench "$arch --eval 'm5 exit' --gem5 -- --cpu-type=HPI ${caches}"
|
||||
bench "$arch --eval 'm5 exit' --emulator gem5 -- --cpu-type=HPI ${caches}"
|
||||
gem5_insts "$arch"
|
||||
fi
|
||||
|
||||
@ -83,12 +83,12 @@ if [ "$test_size" -ge 2 ]; then
|
||||
gem5_insts "$arch"
|
||||
fi
|
||||
if [ "$test_size" -ge 3 ]; then
|
||||
bench "$arch --eval 'm5 exit' --gem5 -- --cpu-type=HPI ${caches}"
|
||||
bench "$arch --eval 'm5 exit' --emulator gem5 -- --cpu-type=HPI ${caches}"
|
||||
gem5_insts "$arch"
|
||||
#bench "$arch --eval 'm5 exit' --gem5 --gem5-script biglittle"
|
||||
#bench "$arch --eval 'm5 exit' --emulator gem5 --gem5-script biglittle"
|
||||
#gem5_insts "$arch"
|
||||
bench "$arch --eval 'm5 exit' --gem5 --gem5-build-type fast"
|
||||
bench "$arch --eval 'm5 exit' --emulator gem5 --gem5-build-type fast"
|
||||
gem5_insts "$arch"
|
||||
bench "$arch --eval 'm5 exit' --gem5 --gem5-build-type debug"
|
||||
bench "$arch --eval 'm5 exit' --emulator gem5 --gem5-build-type debug"
|
||||
gem5_insts "$arch"
|
||||
fi
|
||||
|
||||
80
common.py
80
common.py
@ -95,7 +95,15 @@ consts['obj_ext'] = '.o'
|
||||
consts['config_file'] = os.path.join(consts['data_dir'], 'config.py')
|
||||
consts['magic_fail_string'] = b'lkmc_test_fail'
|
||||
consts['baremetal_lib_basename'] = 'lib'
|
||||
consts['emulators'] = ['qemu', 'gem5']
|
||||
consts['emulator_short_to_long_dict'] = collections.OrderedDict([
|
||||
('q', 'qemu'),
|
||||
('g', 'gem5'),
|
||||
])
|
||||
consts['all_long_emulators'] = [consts['emulator_short_to_long_dict'][k] for k in consts['emulator_short_to_long_dict']]
|
||||
consts['emulator_choices'] = set()
|
||||
for key in consts['emulator_short_to_long_dict']:
|
||||
consts['emulator_choices'].add(key)
|
||||
consts['emulator_choices'].add(consts['emulator_short_to_long_dict'][key])
|
||||
|
||||
class LkmcCliFunction(cli_function.CliFunction):
|
||||
'''
|
||||
@ -130,7 +138,12 @@ Run action for all supported --archs archs. Ignore --archs.
|
||||
'''.format(arches_string)
|
||||
)
|
||||
self.add_argument(
|
||||
'-a', '--arch', action='append', default=[consts['default_arch']], dest='archs',
|
||||
'-a',
|
||||
'--arch',
|
||||
action='append',
|
||||
choices=consts['arch_choices'],
|
||||
default=[consts['default_arch']],
|
||||
dest='archs',
|
||||
help='''\
|
||||
CPU architecture to use. If given multiple times, run the action
|
||||
for each arch sequentially in that order. If one of them fails, stop running.
|
||||
@ -298,17 +311,29 @@ instances in parallel. Default: the run ID (-n) if that is an integer, otherwise
|
||||
)
|
||||
|
||||
# Misc.
|
||||
emulators = consts['emulator_short_to_long_dict']
|
||||
emulators_string = []
|
||||
for emulator_short in emulators:
|
||||
emulator_long = emulators[emulator_short]
|
||||
emulators_string.append('{} ({})'.format(emulator_long, emulator_short))
|
||||
emulators_string = ', '.join(emulators_string)
|
||||
self.add_argument(
|
||||
'--emulator', choices=consts['emulators'],
|
||||
'--all-emulators', default=False,
|
||||
help='''\
|
||||
Set the emulator to use. Ignore --gem5.
|
||||
'''
|
||||
Run action for all supported --emulators emulators. Ignore --emulators.
|
||||
'''.format(emulators_string)
|
||||
)
|
||||
self.add_argument(
|
||||
'-g', '--gem5', default=False,
|
||||
'-e',
|
||||
'--emulator',
|
||||
action='append',
|
||||
choices=consts['emulator_choices'],
|
||||
default=['qemu'],
|
||||
dest='emulators',
|
||||
help='''\
|
||||
Use gem5 instead of QEMU. Shortcut for `--emulator gem5`.
|
||||
'''
|
||||
Emulator to use. If given multiple times, semantics are similar to --arch.
|
||||
Valid emulators: {}
|
||||
'''.format(emulators_string)
|
||||
)
|
||||
|
||||
def __call__(self, **kwargs):
|
||||
@ -328,15 +353,10 @@ Use gem5 instead of QEMU. Shortcut for `--emulator gem5`.
|
||||
'''
|
||||
def join(*paths):
|
||||
return os.path.join(*paths)
|
||||
if env['arch'] not in consts['arch_choices']:
|
||||
raise Exception('Unknown arch: ' + env['arch'])
|
||||
if env['emulator'] is None:
|
||||
if env['gem5']:
|
||||
env['emulator'] = 'gem5'
|
||||
else:
|
||||
env['emulator'] = 'qemu'
|
||||
if env['arch'] in env['arch_short_to_long_dict']:
|
||||
env['arch'] = env['arch_short_to_long_dict'][env['arch']]
|
||||
if env['emulator'] in env['emulator_short_to_long_dict']:
|
||||
env['emulator'] = env['emulator_short_to_long_dict'][env['emulator']]
|
||||
if env['userland_build_id'] is None:
|
||||
env['userland_build_id'] = env['default_build_id']
|
||||
env['userland_build_id_given'] = False
|
||||
@ -722,19 +742,23 @@ Use gem5 instead of QEMU. Shortcut for `--emulator gem5`.
|
||||
env.update(consts)
|
||||
if env['all_archs']:
|
||||
env['archs'] = consts['all_long_archs']
|
||||
for arch in env['archs']:
|
||||
if not env['dry_run']:
|
||||
start_time = time.time()
|
||||
env['arch'] = arch
|
||||
self.env = env.copy()
|
||||
self._init_env(self.env)
|
||||
self.sh = shell_helpers.ShellHelpers(dry_run=self.env['dry_run'])
|
||||
ret = self.timed_main()
|
||||
if not env['dry_run']:
|
||||
end_time = time.time()
|
||||
self._print_time(end_time - start_time)
|
||||
if ret is not None and ret != 0:
|
||||
return ret
|
||||
if env['all_emulators']:
|
||||
env['emulators'] = consts['all_long_emulators']
|
||||
for emulator in env['emulators']:
|
||||
for arch in env['archs']:
|
||||
if not env['dry_run']:
|
||||
start_time = time.time()
|
||||
env['arch'] = arch
|
||||
env['emulator'] = emulator
|
||||
self.env = env.copy()
|
||||
self._init_env(self.env)
|
||||
self.sh = shell_helpers.ShellHelpers(dry_run=self.env['dry_run'])
|
||||
ret = self.timed_main()
|
||||
if not env['dry_run']:
|
||||
end_time = time.time()
|
||||
self._print_time(end_time - start_time)
|
||||
if ret is not None and ret != 0:
|
||||
return ret
|
||||
return 0
|
||||
|
||||
def make_build_dirs(self):
|
||||
|
||||
@ -13,7 +13,7 @@ while getopts "C" OPT; do
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
common_opts="--gem5 $@"
|
||||
common_opts="--emulator gem5 $@"
|
||||
|
||||
# Vars
|
||||
cmd="./run ${common_opts}"
|
||||
|
||||
@ -6,7 +6,7 @@ set -eu
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
|
||||
outfile="${root_dir}/out/gem5-bench-dhrystone.txt"
|
||||
arch=aarch64
|
||||
cmd="./run -a '$arch' --gem5 --eval-busybox '/gem5.sh'"
|
||||
cmd="./run --arch '$arch' --emulator gem5 --eval-busybox '/gem5.sh'"
|
||||
|
||||
# These cache sizes roughly match the ARM Cortex A75
|
||||
# https://en.wikipedia.org/wiki/ARM_Cortex-A75
|
||||
|
||||
7
run
7
run
@ -59,7 +59,7 @@ See: https://github.com/cirosantilli/linux-kernel-module-cheat#replace-init
|
||||
'''
|
||||
)
|
||||
self.add_argument(
|
||||
'-e', '--kernel-cli',
|
||||
'--kernel-cli',
|
||||
help='''\
|
||||
Pass an extra Linux kernel command line options, and place them before
|
||||
the dash separator `-`. Only options that come before the `-`, i.e.
|
||||
@ -76,14 +76,13 @@ See: https://github.com/cirosantilli/linux-kernel-module-cheat#init-busybox
|
||||
'''
|
||||
)
|
||||
self.add_argument(
|
||||
'-f', '--kernel-cli-after-dash',
|
||||
'--kernel-cli-after-dash',
|
||||
help='''\
|
||||
Pass an extra Linux kernel command line options, add a dash `-`
|
||||
separator, and place the options after the dash. Intended for custom
|
||||
options understood by our `init` scripts, most of which are prefixed
|
||||
by `lkmc_`.
|
||||
Example: `./run --kernel-cli-after-dash 'lkmc_eval="wget google.com" lkmc_lala=y'`
|
||||
Mnenomic: `-f` comes after `-e`.
|
||||
'''
|
||||
)
|
||||
self.add_argument(
|
||||
@ -92,7 +91,7 @@ Mnenomic: `-f` comes after `-e`.
|
||||
Pass extra options to the gem5 executable.
|
||||
Do not confuse with the arguments passed to config scripts,
|
||||
like `fs.py`. Example:
|
||||
./run -G '--debug-flags=Exec --debug' --gem5 -- --cpu-type=HPI --caches
|
||||
./run --emulator gem5 --gem5-exe-args '--debug-flags=Exec --debug' -- --cpu-type=HPI --caches
|
||||
will run:
|
||||
gem.op5 --debug-flags=Exec fs.py --cpu-type=HPI --caches
|
||||
'''
|
||||
|
||||
65
test-gdb
65
test-gdb
@ -21,41 +21,40 @@ found by searching for the Python test files.
|
||||
def timed_main(self):
|
||||
run = self.import_path('run').Main()
|
||||
run_gdb = self.import_path('run-gdb').Main()
|
||||
for emulator in self.env['emulators']:
|
||||
if self.env['arch'] in self.env['crosstool_ng_supported_archs']:
|
||||
if self.env['tests'] == []:
|
||||
test_scripts_noext = []
|
||||
for f in os.listdir(self.env['baremetal_src_dir']):
|
||||
if self.env['arch'] in self.env['crosstool_ng_supported_archs']:
|
||||
if self.env['tests'] == []:
|
||||
test_scripts_noext = []
|
||||
for f in os.listdir(self.env['baremetal_src_dir']):
|
||||
base, ext = os.path.splitext(f)
|
||||
if ext == '.py':
|
||||
test_scripts_noext.append(base)
|
||||
for root, dirs, files in os.walk(os.path.join(self.env['baremetal_src_dir'], 'arch', self.env['arch'])):
|
||||
for f in files:
|
||||
base, ext = os.path.splitext(f)
|
||||
if ext == '.py':
|
||||
test_scripts_noext.append(base)
|
||||
for root, dirs, files in os.walk(os.path.join(self.env['baremetal_src_dir'], 'arch', self.env['arch'])):
|
||||
for f in files:
|
||||
base, ext = os.path.splitext(f)
|
||||
if ext == '.py':
|
||||
full_path = os.path.join(root, base)
|
||||
relpath = os.path.relpath(full_path, self.env['baremetal_src_dir'])
|
||||
test_scripts_noext.append(relpath)
|
||||
else:
|
||||
test_scripts_noext = self.env['tests']
|
||||
for test_script_noext in test_scripts_noext:
|
||||
run_thread = threading.Thread(target=lambda: run(
|
||||
archs=[self.env['arch']],
|
||||
background=True,
|
||||
baremetal=test_script_noext,
|
||||
dry_run=self.env['dry_run'],
|
||||
emulator=emulator,
|
||||
wait_gdb=True
|
||||
))
|
||||
run_thread.start()
|
||||
run_gdb(
|
||||
archs=[self.env['arch']],
|
||||
baremetal=test_script_noext,
|
||||
dry_run=self.env['dry_run'],
|
||||
emulator=emulator,
|
||||
test=True,
|
||||
)
|
||||
run_thread.join()
|
||||
full_path = os.path.join(root, base)
|
||||
relpath = os.path.relpath(full_path, self.env['baremetal_src_dir'])
|
||||
test_scripts_noext.append(relpath)
|
||||
else:
|
||||
test_scripts_noext = self.env['tests']
|
||||
for test_script_noext in test_scripts_noext:
|
||||
run_thread = threading.Thread(target=lambda: run(
|
||||
archs=[self.env['arch']],
|
||||
background=True,
|
||||
baremetal=test_script_noext,
|
||||
dry_run=self.env['dry_run'],
|
||||
emulators=self.env['emulator'],
|
||||
wait_gdb=True
|
||||
))
|
||||
run_thread.start()
|
||||
run_gdb(
|
||||
archs=[self.env['arch']],
|
||||
baremetal=test_script_noext,
|
||||
dry_run=self.env['dry_run'],
|
||||
emulators=self.env['emulator'],
|
||||
test=True,
|
||||
)
|
||||
run_thread.join()
|
||||
|
||||
if __name__ == '__main__':
|
||||
Main().cli()
|
||||
|
||||
@ -13,40 +13,39 @@ class Main(common.LkmcCliFunction):
|
||||
'hello_cpp.cpp',
|
||||
'print_argv.c',
|
||||
]
|
||||
for emulator in self.env['emulators']:
|
||||
if emulator == 'gem5':
|
||||
extra_args = {
|
||||
'userland_build_id': 'static',
|
||||
}
|
||||
else:
|
||||
extra_args = {}
|
||||
if self.env['arch'] == 'x86_64':
|
||||
arch_sources = [
|
||||
'asm_hello'
|
||||
]
|
||||
elif self.env['arch'] == 'aarch64':
|
||||
arch_sources = [
|
||||
'asm_hello'
|
||||
]
|
||||
else:
|
||||
arch_sources = []
|
||||
arch_sources[:] = [os.path.join('arch', self.env['arch'], arch_source) for arch_source in arch_sources]
|
||||
for source in sources + arch_sources:
|
||||
exit_status = run(
|
||||
archs=[self.env['arch']],
|
||||
dry_run=self.env['dry_run'],
|
||||
userland=source,
|
||||
emulator=emulator,
|
||||
**extra_args,
|
||||
)
|
||||
# TODO forward all args attempt. In particular, --dry-run.
|
||||
#new_env = self.env.copy()
|
||||
#new_env['userland'] = source
|
||||
#new_env['emulator'] = emulator
|
||||
#new_env.update(extra_args)
|
||||
#exit_status = run(**new_env)
|
||||
if exit_status != 0:
|
||||
raise Exception('Test failed: {} {} {} {}'.format(emulator, arch, source, exit_status))
|
||||
if self.env['emulator'] == 'gem5':
|
||||
extra_args = {
|
||||
'userland_build_id': 'static',
|
||||
}
|
||||
else:
|
||||
extra_args = {}
|
||||
if self.env['arch'] == 'x86_64':
|
||||
arch_sources = [
|
||||
'asm_hello'
|
||||
]
|
||||
elif self.env['arch'] == 'aarch64':
|
||||
arch_sources = [
|
||||
'asm_hello'
|
||||
]
|
||||
else:
|
||||
arch_sources = []
|
||||
arch_sources[:] = [os.path.join('arch', self.env['arch'], arch_source) for arch_source in arch_sources]
|
||||
for source in sources + arch_sources:
|
||||
exit_status = run(
|
||||
archs=[self.env['arch']],
|
||||
dry_run=self.env['dry_run'],
|
||||
userland=source,
|
||||
emulators=[self.env['emulator']],
|
||||
**extra_args,
|
||||
)
|
||||
# TODO forward all args attempt. In particular, --dry-run.
|
||||
#new_env = self.env.copy()
|
||||
#new_env['userland'] = source
|
||||
#new_env['emulator'] = emulator
|
||||
#new_env.update(extra_args)
|
||||
#exit_status = run(**new_env)
|
||||
if exit_status != 0:
|
||||
raise Exception('Test failed: {} {} {} {}'.format(emulator, arch, source, exit_status))
|
||||
|
||||
if __name__ == '__main__':
|
||||
Main().cli()
|
||||
|
||||
Reference in New Issue
Block a user