qemu: expose rr

run: expose forgotten -Q, document it
This commit is contained in:
Ciro Santilli
2018-08-06 02:03:18 +01:00
parent 2e42a776c5
commit 19f4d00f9b
5 changed files with 104 additions and 14 deletions

View File

@@ -7011,19 +7011,70 @@ TODO do even more awesome offline post-mortem analysis things, such as:
==== QEMU record and replay ==== QEMU record and replay
QEMU supports deterministic record and replay by saving external inputs, which would be awesome to understand the kernel, as you would be able to examine a single run as many times as you would like. QEMU runs are not deterministic by default, however it does support a record and replay mechanism that allows you to replay a previous run deterministically:
This mechanism first requires a trace to be generated on an initial record run. The trace is then used on the replay runs to make them deterministic. This awesome feature allows you to examine a single run as many times as you would like until you understand everything:
Unfortunately it is not working in the current QEMU: https://stackoverflow.com/questions/46970215/how-to-use-qemus-deterministic-record-and-replay-feature-for-a-linux-kernel-boo ....
# Record a run.
./run -F '/rand_check.out;/poweroff.out;' -r
# Replay the run.
./run -F '/rand_check.out;/poweroff.out;' -R
....
Patches were merged in post v2.12.0-rc2 but it crashed for me and I opened a minimized bug report: https://bugs.launchpad.net/qemu/+bug/1762179 By comparing the terminal output of both runs, we can see that they are the exact same, including things which normally differ across runs:
We don't expose record and replay on our scripts yet since it was was not very stable, but we will do so when it stabilizes. * timestamps of dmesg output
* <<rand_check-out>> output
<<rand_check-out>> is a good way to test out if record and replay is actually deterministic. The record and replay feature was revived around QEMU v3.0.0. It existed earlier but it rot completely. As of v3.0.0 it is still flaky: sometimes we get deadlocks, and only a limited number of command line arguments are supported.
Alternatively, https://github.com/mozilla/rr[`mozilla/rr`] claims it is able to run QEMU: but using it would require you to step through QEMU code itself. Likely doable, but do you really want to? Documented at: https://github.com/qemu/qemu/blob/v2.12.0/docs/replay.txt
TODO: using `-r` as above leads to a kernel warning:
....
rcu_sched detected stalls on CPUs/tasks
....
TODO: replay deadlocks intermittently at disk operations, last kernel message:
....
EXT4-fs (sda): re-mounted. Opts: block_validity,barrier,user_xattr
....
TODO replay with network gets stuck:
....
./run -F '/sbin/ifup -a;wget -S google.com;/poweroff.out;' -r
./run -F '/sbin/ifup -a;wget -S google.com;/poweroff.out;' -R
....
after the message:
....
adding dns 10.0.2.3
....
There is explicit network support on the QEMU patches, but either it is buggy or we are not using the correct magic options.
TODO `arm` and `aarch64` only seem to work with initrd since I cannot plug a working IDE disk device? See also: https://lists.gnu.org/archive/html/qemu-devel/2018-02/msg05245.html
Then, when I tried with <<initrd>> and no disk:
....
./build -aA -i
./run -aA -F '/rand_check.out;/poweroff.out;' -i -r
./run -aA -F '/rand_check.out;/poweroff.out;' -i -R
....
QEMU crashes with:
....
ERROR:replay/replay-time.c:49:replay_read_clock: assertion failed: (replay_file && replay_mutex_locked())
....
I had the same error previously on x86-64, but it was fixed: https://bugs.launchpad.net/qemu/+bug/1762179 so maybe the forgot to fix it for `aarch64`?
==== QEMU trace multicore ==== QEMU trace multicore

View File

@@ -35,6 +35,7 @@
on top of it. on top of it.
|`-M` |`VARIANT` |gem5 build variant. |`-M` |`VARIANT` |gem5 build variant.
|`-p` | |Pass extra arguments to the `rootfs_post_build_script`. |`-p` | |Pass extra arguments to the `rootfs_post_build_script`.
|`-Q` |`VARIANT`` |QEMU build variant.
|`-S` | |Don't build QEMU with SDL support. |`-S` | |Don't build QEMU with SDL support.
Graphics such as X11 won't work, only the terminal. Graphics such as X11 won't work, only the terminal.
|`-s` | |Add a custom suffix to the build. |`-s` | |Add a custom suffix to the build.

3
common
View File

@@ -69,7 +69,8 @@ set_common_vars() {
common_images_dir="${buildroot_out_dir}/images" common_images_dir="${buildroot_out_dir}/images"
host_dir="${buildroot_out_dir}/host" host_dir="${buildroot_out_dir}/host"
common_qemu_run_dir="${out_arch_dir}/qemu/${common_run_id}" common_qemu_run_dir="${out_arch_dir}/qemu/${common_run_id}"
common_qemu_termout_file="${common_qemu_run_dir}/termout.txt" common_qemu_termout_file="${common_qemu_run_dir}/termout.txt"
common_qemu_rrfile="${common_qemu_run_dir}/rrfile"
common_linux_custom_dir="${build_dir}/linux-custom" common_linux_custom_dir="${build_dir}/linux-custom"
common_linux_variant_dir="${common_linux_custom_dir}.${linux_variant}" common_linux_variant_dir="${common_linux_custom_dir}.${linux_variant}"
common_qemu_custom_dir="${build_dir}/host-qemu-custom" common_qemu_custom_dir="${build_dir}/host-qemu-custom"

46
run
View File

@@ -27,6 +27,7 @@ initramfs=false
memory=256M memory=256M
nographic=true nographic=true
prebuilt=false prebuilt=false
rr=
root= root=
tmux=false tmux=false
tmux_args= tmux_args=
@@ -35,7 +36,7 @@ trace_enabled=false
# just to prevent QEMU from emitting a warning that '' is not valid. # just to prevent QEMU from emitting a warning that '' is not valid.
trace_type=pr_manager_run trace_type=pr_manager_run
vnc= vnc=
while getopts a:c:DdE:e:F:f:G:ghIiKkL:M:m:N:n:PT:t:U:uVX:x OPT; do while getopts a:c:DdE:e:F:f:G:ghIiKkL:M:m:N:n:PQ:RrT:t:U:uVX:x OPT; do
case "$OPT" in case "$OPT" in
a) a)
arch="$OPTARG" arch="$OPTARG"
@@ -108,6 +109,15 @@ while getopts a:c:DdE:e:F:f:G:ghIiKkL:M:m:N:n:PT:t:U:uVX:x OPT; do
P) P)
prebuilt=true prebuilt=true
;; ;;
Q)
common_qemu_variant="$OPTARG"
;;
R)
rr=replay
;;
r)
rr=record
;;
T) T)
trace_enabled=true trace_enabled=true
trace_type="$OPTARG" trace_type="$OPTARG"
@@ -209,7 +219,7 @@ ${gem5opts} \
--dtb "${common_gem5_system_dir}/arm/dt/armv8_gem5_v1_big_little_2_2.dtb" \\ --dtb "${common_gem5_system_dir}/arm/dt/armv8_gem5_v1_big_little_2_2.dtb" \\
--kernel="${common_vmlinux}" \\ --kernel="${common_vmlinux}" \\
--little-cpus=2 \\ --little-cpus=2 \\
${extra_flags} \\ ${extra_flags} \
" "
else else
gem5_common="\ gem5_common="\
@@ -282,16 +292,39 @@ ${vnc}"
extra_flags="${extra_flags} -initrd '${common_images_dir}/rootfs.cpio' \\ extra_flags="${extra_flags} -initrd '${common_images_dir}/rootfs.cpio' \\
" "
fi fi
# Disk related options.
if "$ramfs"; then if "$ramfs"; then
# TODO why is this needed, and why any string works. # TODO why is this needed, and why any string works.
root='root=/dev/anything' root='root=/dev/anything'
else else
if [ ! "$arch" = mips64 ]; then if [ ! "$arch" = mips64 ]; then
extra_flags="${extra_flags} -drive 'file=${common_images_dir}/rootfs.ext2.qcow2,format=qcow2,if=virtio,snapshot' \\ if [ -n "$rr" ]; then
driveif=none
rrid=',id=img-direct'
root='root=/dev/sda'
else
driveif=virtio
root='root=/dev/vda'
rrid=
fi
extra_flags="${extra_flags} -drive 'file=${common_images_dir}/rootfs.ext2.qcow2,format=qcow2,if=${driveif},snapshot${rrid}' \\
" "
root='root=/dev/vda' if [ -n "$rr" ]; then
extra_flags="${extra_flags} \\
-drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay \\
-device ide-hd,drive=img-blkreplay \\
"
fi
fi fi
fi fi
if [ -n "$rr" ]; then
extra_flags="${extra_flags} \
-object filter-replay,id=replay,netdev=net0 \\
-icount 'shift=7,rr=${rr},rrfile=${common_qemu_rrfile}' \\
"
fi
case "$arch" in case "$arch" in
x86_64) x86_64)
if "$kgdb"; then if "$kgdb"; then
@@ -342,7 +375,8 @@ ${extra_flags} \
mips64) mips64)
if ! "$ramfs"; then if ! "$ramfs"; then
root='root=/dev/hda' root='root=/dev/hda'
extra_flags="${extra_flags} -drive 'file=${common_images_dir}/rootfs.ext2.qcow2,format=qcow2,snapshot' \\ extra_flags="${extra_flags} \
-drive 'file=${common_images_dir}/rootfs.ext2.qcow2,format=qcow2,snapshot' \\
" "
fi fi
cmd="\ cmd="\
@@ -359,7 +393,7 @@ fi
if "$tmux"; then if "$tmux"; then
if "$gem5"; then if "$gem5"; then
eval "./tmu 'sleep 2;./gem5-shell -n ${common_run_id} ${tmux_args};'" eval "./tmu 'sleep 2;./gem5-shell -n ${common_run_id} ${tmux_args};'"
elif "$debug"; then elif "$debug"; then
eval "./tmu ./rungdb -a '${arch} -L ${common_linux_variant}' -n ${common_run_id} ${tmux_args}" eval "./tmu ./rungdb -a '${arch} -L ${common_linux_variant}' -n ${common_run_id} ${tmux_args}"
fi fi
fi fi

View File

@@ -44,7 +44,10 @@
Any Any
|`-N` |`VARIANT` |gem5 source input variant. |`-N` |`VARIANT` |gem5 source input variant.
|`-n` | |Run ID. |`-n` | |Run ID.
|`-R` | |Replay a QEMU run record deterministically.
|`-r` | |Record a QEMU run record for later replay with `-R`.
|`-P` | |Run the downloaded prebuilt images. |`-P` | |Run the downloaded prebuilt images.
|`-Q` |`VARIANT`` |QEMU build variant.
|`-T` |`TRACE_TYPES` |Set trace events to be enabled. |`-T` |`TRACE_TYPES` |Set trace events to be enabled.
If not given, gem5 tracing is completely disabled, while QEMU tracing If not given, gem5 tracing is completely disabled, while QEMU tracing
is enabled but uses default traces that are very rare and don't affect is enabled but uses default traces that are very rare and don't affect