diff --git a/README.adoc b/README.adoc index e5335be..7b9ad81 100644 --- a/README.adoc +++ b/README.adoc @@ -1017,10 +1017,10 @@ but why not just use your super simple and effective `/poweroff.out` and be done === Run command at the end of BusyBox init -If you rely on something that BusyBox' init set up for you like networking, you caould do: +If you rely on something that BusyBox' init set up for you like networking, you could do: .... -./run -e '- lkmc_eval="insmod /hello.ko;wget -S google.com;poweroff.out;"' +./run -f 'lkmc_eval="insmod /hello.ko;wget -S google.com;poweroff.out;"' .... The `lkmc_eval` option gets evaled by our default `S98` startup script if present. @@ -1073,16 +1073,10 @@ Finally, the docs are lying, arguments with dots that come after `-` are still t The default BusyBox init scripts enable networking, and there is a 15 second timeout in case your network is down or if your kernel / emulator setup does not support it. -To disable networking, use: +We have hacked it up so that you can disable networking with: .... -./build -p -n -.... - -To restore it, run: - -.... -./build -- initscripts-reconfigure +./run -f 'lkmc_nonet=y' .... == KVM @@ -2951,7 +2945,7 @@ which is very close to the end of the boot. Increasing the memory from 256M to 5 === gem5 limitations * networking not working. We currently just disable it from `inittab` by default to prevent waiting at startup -* `gdbserver`: https://stackoverflow.com/questions/48941494/how-to-do-port-forwarding-from-guest-to-host-in-gem5 +* could not do port forwarding from host to guest, and therefore use `gdbserver`: https://stackoverflow.com/questions/48941494/how-to-do-port-forwarding-from-guest-to-host-in-gem5 ==== gem5 x86_64 limitations @@ -2962,7 +2956,6 @@ which is very close to the end of the boot. Increasing the memory from 256M to 5 [ 0.000000] clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645519600211568 ns .... - == Insane action === Run on host @@ -3309,6 +3302,16 @@ include::rootfs_overlay/README.adoc[] :leveloffset: -3 +=== Script man pages + +:leveloffset: +3 + +include::build-usage.adoc[] + +include::run-usage.adoc[] + +:leveloffset: -3 + :leveloffset: +2 include::CONTRIBUTING.adoc[] diff --git a/br2 b/br2 index 52238ce..8eda4ea 100644 --- a/br2 +++ b/br2 @@ -28,6 +28,9 @@ BR2_TOOLCHAIN_BUILDROOT_CXX=y BR2_TOOLCHAIN_BUILDROOT_FORTRAN=y BR2_TOOLCHAIN_BUILDROOT_WCHAR=y +# We use our own to turn it on and off at runtime. +BR2_PACKAGE_IFUPDOWN_SCRIPTS=n + # lscpu: TODO not installing? BR2_PACKAGE_UTIL_LINUX=y BR2_PACKAGE_UTIL_LINUX_BINARIES=y diff --git a/build b/build index 863e613..58e3071 100755 --- a/build +++ b/build @@ -76,7 +76,7 @@ BR2_TARGET_ROOTFS_INITRAMFS=n done shift $(($OPTIND - 1)) extra_make_args="$extra_make_args $@" -set_common_vars "$arch" +set_common_vars "$arch" "$gem5" case "$arch" in x86_64) defconfig=qemu_x86_64_defconfig @@ -91,9 +91,7 @@ case "$arch" in defconfig=qemu_mips64r6_malta_defconfig ;; esac -if "$gem5"; then - post_script_args="$post_script_args -n" -else +if ! "$gem5"; then config_fragments="$config_fragments br2_qemu" fi config_fragments="$config_fragments br2_cli.gitignore" diff --git a/common b/common index 2de3fa8..8f544d7 100644 --- a/common +++ b/common @@ -1,6 +1,7 @@ #!/usr/bin/env bash set_common_vars() { arch="$1" + gem5="$2" root_dir="$(pwd)" buildroot_dir="${root_dir}/buildroot" arch_dir="$arch" diff --git a/count-boot-instructions b/count-boot-instructions index d9ed12d..4ac66a7 100755 --- a/count-boot-instructions +++ b/count-boot-instructions @@ -1,7 +1,17 @@ #!/usr/bin/env bash -set -e -time ./run -n -e 'init=/poweroff.out' -- -trace exec_tb,file=trace -time ./qemu/scripts/simpletrace.py buildroot/output.x86_64~/build/host-qemu-custom/trace-events-all trace >trace.txt +set -eu +. common +arch=x86_64 +while getopts a: OPT; do + case "$OPT" in + a) + arch="$OPTARG" + ;; + esac +done +set_common_vars "$arch" false +time ./run -a "$arch" -n -e 'init=/poweroff.out' -- -trace exec_tb,file=trace +time ./qemu/scripts/simpletrace.py "${out_dir}/build/host-qemu-custom/trace-events-all" trace >trace.txt wc -l trace.txt sed '/0x1000000/q' trace.txt >trace-boot.txt wc -l trace-boot.txt diff --git a/parsec-benchmark/parsec-benchmark b/parsec-benchmark/parsec-benchmark index 6946dbf..727a56b 160000 --- a/parsec-benchmark/parsec-benchmark +++ b/parsec-benchmark/parsec-benchmark @@ -1 +1 @@ -Subproject commit 6946dbf03c5a5b7d3f2f1cfe88eac90dc546bfdc +Subproject commit 727a56bf4bf25566c93e1f77ae4e5d32dfa4da6b diff --git a/rootfs_overlay/etc/init.d/S40network b/rootfs_overlay/etc/init.d/S40network new file mode 100755 index 0000000..c440941 --- /dev/null +++ b/rootfs_overlay/etc/init.d/S40network @@ -0,0 +1,44 @@ +#!/bin/sh + +# Copied from: package/ifupdown-scripts/S40network at +# 8ce27bb9fee80a406a4199657ef90e3c315e7457 +# +# We then just added this line to turn it off at runtime. +# +# We also considered copying the file at build to / and then +# sourcing it from S98 to be a bit DRYer, but it wouldn't work +# very well if some S50 requires networking to work. +# +# This became necessary nitially when aarch64 qemu and gem5 +# started using the same Buildroot output directory. +[ -n "$lkmc_nonet" ] && exit 0 + +# +# Start the network.... +# + +# Debian ifupdown needs the /run/network lock directory +mkdir -p /run/network + +case "$1" in + start) + printf "Starting network: " + /sbin/ifup -a + [ $? = 0 ] && echo "OK" || echo "FAIL" + ;; + stop) + printf "Stopping network: " + /sbin/ifdown -a + [ $? = 0 ] && echo "OK" || echo "FAIL" + ;; + restart|reload) + "$0" stop + "$0" start + ;; + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac + +exit $? + diff --git a/rootfs_post_build_script b/rootfs_post_build_script index 955bb80..529a356 100755 --- a/rootfs_post_build_script +++ b/rootfs_post_build_script @@ -5,19 +5,6 @@ # To test it out, arguments can be passed with: # make BR2_ROOTFS_POST_SCRIPT_ARGS="asdf qwer" target_dir="$1" -shift -net=true -while getopts 'n' OPT; do - case "$OPT" in - n) - net=false - ;; - esac -done -shift $(($OPTIND - 1)) -if ! "$net"; then - rm -f "${target_dir}/etc/init.d/"S*network -fi mkdir -p \ "${target_dir}/mnt/9p" \ "${target_dir}/mnt/out" \ diff --git a/run b/run index c9486b9..ca75f21 100755 --- a/run +++ b/run @@ -13,6 +13,7 @@ kvm=false # nokaslr: https://unix.stackexchange.com/questions/397939/turning-off-kaslr-to-debug-linux-kernel-using-qemu-and-gdb # Turned on by default since v4.12 extra_append='nokaslr norandmaps printk.devkmsg=on printk.time=y' +extra_append_after_dash='' extra_flags='' extra_flags_qemu='' gem5=false @@ -23,7 +24,7 @@ initramfs=false memory=256M nographic=false root='' -while getopts a:c:DdE:e:G:gIiKkm:nt:x OPT; do +while getopts a:c:DdE:e:f:G:gIiKkm:nt:x OPT; do case "$OPT" in a) arch="$OPTARG" @@ -43,6 +44,9 @@ while getopts a:c:DdE:e:G:gIiKkm:nt:x OPT; do e) extra_append="$extra_append $OPTARG" ;; + f) + extra_append_after_dash="$extra_append_after_dash $OPTARG" + ;; K) kvm=true ;; @@ -79,7 +83,7 @@ while getopts a:c:DdE:e:G:gIiKkm:nt:x OPT; do done shift "$(($OPTIND - 1))" extra_flags="$extra_flags $@" -set_common_vars "$arch" +set_common_vars "$arch" "$gem5" if "$initrd" || "$initramfs"; then ramfs=true else @@ -91,12 +95,19 @@ if [ -n "$lkmc_eval" ]; then else initarg="init" fi - extra_append="${extra_append} ${initarg}=/eval_base64.sh - lkmc_eval=\"$(printf "$lkmc_eval" | base64)\"" + extra_append="${extra_append} ${initarg}=/eval_base64.sh" + extra_append_after_dash="${extra_append_after_dash} lkmc_eval=\"$(printf "$lkmc_eval" | base64)\"" fi if "$nographic" && [ "$arch" = x86_64 ]; then extra_append="$extra_append console=ttyS0" extra_flags_qemu="$extra_flags_qemu -nographic" fi +if "$gem5"; then + extra_append_after_dash="${extra_append_after_dash} lkmc_nonet=y" +fi +if [ -n "$extra_append_after_dash" ]; then + extra_append="${extra_append} - ${extra_append_after_dash}" +fi if "$gem5"; then build_dir="${out_dir}/build/gem5-1.0" @@ -125,15 +136,16 @@ ${gem5opts} \ if "$kvm"; then extra_flags="$extra_flags --cpu-type=X86KvmCPU" fi - cmd="${gem5_common} \ ---command-line='earlyprintk=ttyS0 console=ttyS0 lpj=7999923 root=/dev/hda $extra_append' \ -$extra_flags \ + cmd="\ +${gem5_common} \ +--command-line='earlyprintk=ttyS0 console=ttyS0 lpj=7999923 root=/dev/hda ${extra_append}' \ +${extra_flags} \ " elif [ "$arch" = arm ] || [ "$arch" = aarch64 ]; then # TODO why is it mandatory to pass mem= here? Not true for QEMU. # Anything smaller than physical blows up as expected, but why can't it auto-detect the right value? cmd="${gem5_common} \ ---command-line='earlyprintk=pl011,0x1c090000 console=ttyAMA0 lpj=19988480 rw loglevel=8 mem=${memory} root=/dev/sda $extra_append' \ +--command-line='earlyprintk=pl011,0x1c090000 console=ttyAMA0 lpj=19988480 rw loglevel=8 mem=${memory} root=/dev/sda ${extra_append}' \ --dtb-file='${gem5_dir}/system/arm/dt/$([ "$arch" = arm ] && echo "armv7_gem5_v1_${cpus}cpu" || echo "armv8_gem5_v1_${cpus}cpu").dtb' \ --machine-type=VExpress_GEM5_V1 \ ${extra_flags} \ @@ -157,19 +169,22 @@ ${debug_vm} \ if "$initrd"; then extra_flags="${extra_flags} -initrd '${images_dir}/rootfs.cpio'" fi + if "$ramfs"; then + # TODO why is this needed, and why any string works. + root='root=/dev/anything' + fi # The base QEMU commands are found under board/qemu/*/readme.tx case "$arch" in x86_64) if "$kgdb"; then extra_append="${extra_append} kgdboc=ttyS0,115200" fi - if "$ramfs"; then - root='root=/dev/anything' - else + if ! "$ramfs"; then root='root=/dev/vda' extra_flags="${extra_flags} -drive file='${images_dir}/rootfs.ext2.qcow2,if=virtio,format=qcow2'" fi - cmd="${qemu_common} \ + cmd="\ +${qemu_common} \ -M pc \ -append '${root} nopat ${extra_append}' \ -device edu \ @@ -183,13 +198,12 @@ ${extra_flags} \ if "$kgdb"; then extra_append="${extra_append} kgdboc=ttyAMA0,115200" fi - if "$ramfs"; then - root='root=/dev/anything' - else + if ! "$ramfs"; then extra_flags="${extra_flags} -drive file='${images_dir}/rootfs.ext2.qcow2,if=scsi,format=qcow2'" root='root=/dev/sda' fi - cmd="$qemu_common \ + cmd="\ +$qemu_common \ -M versatilepb \ -append '${root} ${extra_append}' \ -device rtl8139,netdev=net0 \ @@ -203,13 +217,12 @@ $extra_flags \ if "$kgdb"; then extra_append="${extra_append} kgdboc=ttyAMA0,115200" fi - if "$ramfs"; then - root='root=/dev/anything' - else + if ! "$ramfs"; then root='root=/dev/vda' extra_flags="${extra_flags} -drive file='${images_dir}/rootfs.ext2.qcow2,if=virtio,format=qcow2'" fi - cmd="${qemu_common} \ + cmd="\ +${qemu_common} \ -M virt \ -append '${root} ${extra_append}' \ -cpu cortex-a57 \ @@ -221,13 +234,12 @@ ${extra_flags} \ " ;; mips64) - if "$ramfs"; then - root='root=/dev/anything' - else + if ! "$ramfs"; then root='root=/dev/hda' extra_flags="${extra_flags} -drive file='${images_dir}/rootfs.ext2.qcow2,format=qcow2'" fi - cmd="${qemu_common} \ + cmd="\ +${qemu_common} \ -M malta \ -append '${root} ${extra_append}' \ -cpu I6400 \ diff --git a/run-usage.adoc b/run-usage.adoc index 25650e5..4d86b65 100644 --- a/run-usage.adoc +++ b/run-usage.adoc @@ -14,8 +14,17 @@ |`-E` |`CMDSTR` | Replace the normal init with a minimal init that just evals with given `CMDSTR` bash command string. Example: `-E 'insmod /hello.ko;'` -|`-e` |`CLI_OPTIONS` | Pass an extra Linux kernel command line options. +|`-e` |`CLI_OPTIONS` | Pass an extra Linux kernel command line options, + and place them before the dash separator `-`. + Only options that come before the `-`, i.e. "standard" + options, should be passed with this option. Example: `./run -a arm -e 'init=/poweroff.out'` +|`-f` |`CLI_OPTIONS` | 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_`, e.g.: + `./run -f 'lkmc_eval="wget google.com" lkmc_nonet=y'` + Mnenomic: comes after `-e`. |`-K` | | Use KVM. Only works if guest arch == host arch. |`-k` | | Enable KGDB. |`-G` | | Pass extra options to the gem5 executable. diff --git a/rungdb b/rungdb index 6202378..f1a369e 100755 --- a/rungdb +++ b/rungdb @@ -1,7 +1,6 @@ #!/usr/bin/env bash - -set -e - +set -eu +. common arch='x86_64' bdfore='' gem5=false @@ -39,17 +38,16 @@ else arch_dir="$arch" port=1234 fi - -buildroot_out_dir="$(pwd)/buildroot/output.${arch_dir}~" -gdb="${buildroot_out_dir}/host/usr/bin/${arch}-linux-gdb $before" -cd "${buildroot_out_dir}/build/linux-custom/" +set_common_vars "$arch" "$gem5" +gdb="${out_dir}/host/usr/bin/${arch}-linux-gdb $before" +cd "${out_dir}/build/linux-custom/" if "$kgdb"; then cmd="$gdb \ - -q \ - -ex 'add-auto-load-safe-path $(pwd)' \ - -ex 'file vmlinux' \ - -ex 'target remote localhost:$port' - " +-q \ +-ex 'add-auto-load-safe-path $(pwd)' \ +-ex 'file vmlinux' \ +-ex 'target remote localhost:$port' +" else case "$arch" in 'x86_64') diff --git a/rungdb-user b/rungdb-user index 9ae2d88..e075f86 100755 --- a/rungdb-user +++ b/rungdb-user @@ -1,12 +1,17 @@ #!/usr/bin/env bash -set -e +set -eu +. common usage="$0 []" arch='x86_64' -while getopts a:h OPT; do +gem5=false +while getopts a:gh OPT; do case "$OPT" in a) arch="$OPTARG" ;; + g) + gem5=true + ;; h) echo "$usage" exit 0 @@ -22,9 +27,9 @@ if [ "$#" -gt 0 ]; then else brk='' fi -buildroot_out_dir="$(pwd)/buildroot/output.${arch}~" -executable="${buildroot_out_dir}/build/${executable_rel}" -readelf="${buildroot_out_dir}/host/usr/bin/${arch}-linux-readelf" +set_common_vars "$arch" "$gem5" +executable="${out_dir}/build/${executable_rel}" +readelf="${out_dir}/host/usr/bin/${arch}-linux-readelf" addr="$("$readelf" -h "$executable" | awk '/Entry/{ print $NF }' )" ex="-ex \"add-symbol-file $executable $addr\"" # Twice because lx-symbols overrides our add-symbol-file commands. diff --git a/rungdbserver b/rungdbserver index c45ccc7..80ac184 100755 --- a/rungdbserver +++ b/rungdbserver @@ -1,20 +1,26 @@ -#!/bin/sh +#!/usr/bin/env bash +set -eu +. common arch='x86_64' -while getopts a:k OPT; do +gem5=false +while getopts a:g OPT; do case "$OPT" in a) arch="$OPTARG" ;; + g) + gem5=true + ;; esac done shift "$(($OPTIND - 1))" executable="$1" -buildroot_out_dir="$(pwd)/buildroot/output.${arch}~" -"${buildroot_out_dir}/host/usr/bin/${arch}-linux-gdb" \ - -q \ - -ex "set sysroot ${buildroot_out_dir}/staging" \ - -ex 'target remote localhost:45455' \ - -ex 'tb main' \ - -ex 'c' \ - "${buildroot_out_dir}/build/${executable}" \ +set_common_vars "$arch" "$gem5" +"${out_dir}/host/usr/bin/${arch}-linux-gdb" \ + -q \ + -ex "set sysroot ${out_dir}/staging" \ + -ex 'target remote localhost:45455' \ + -ex 'tb main' \ + -ex 'c' \ + "${out_dir}/build/${executable}" \ ;