Delay AMO rd write until store succeeds#141
Conversation
|
@shengwen-tw I have started the AI code review. It will take a few minutes to complete. |
Do not commit the AMO destination register before the store succeeds. `AMO_OP` wrote `rd` before confirming that `mmu_store()` succeeded. If the store raised a fault, such as a COW/page fault, the destination register could be committed even though the guest kernel would handle the fault and retry the same instruction. This patch delays the `rd` write until after `mmu_store()` returns and `vm->error` is known to be clear.
|
Hi @shengwen-tw , I got a kernel panic when executing $ ./semu -k Image -c 1 -b minimal.dtb -H -d ext4.img
...
[ 0.023338] /dev/root: Can't open blockdev
[ 0.023341] VFS: Cannot open root device "" or unknown-block(0,0): error -6
[ 0.023344] Please append a correct "root=" boot option; here are the available partitions:
[ 0.023347] fe00 262144 vda
[ 0.023348] driver: virtio_blk
[ 0.023350] List of all bdev filesystems:
[ 0.023352] ext3
[ 0.023353] ext4
[ 0.023354] fuseblk
[ 0.023356]
[ 0.023358] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[ 0.023361] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.94 #1
[ 0.023364] Hardware name: semu (DT)
[ 0.023366] Call Trace:
[ 0.023368] [<c0004aa4>] dump_backtrace+0x2c/0x3c
[ 0.023371] [<c04794ac>] show_stack+0x40/0x54
[ 0.023374] [<c047efdc>] dump_stack_lvl+0x74/0xa8
[ 0.023377] [<c047f02c>] dump_stack+0x1c/0x2c
[ 0.023380] [<c047985c>] panic+0x128/0x368
[ 0.023383] [<c0488cdc>] mount_root_generic+0x214/0x2a8
[ 0.023386] [<c0488ddc>] mount_root+0x6c/0x1d4
[ 0.023390] [<c0489148>] prepare_namespace+0x204/0x258
[ 0.023393] [<c04885a0>] kernel_init_freeable+0x1dc/0x220
[ 0.023397] [<c04803ac>] kernel_init+0x24/0x120
[ 0.023400] [<c0487294>] ret_from_exception_end+0x14/0x20
[ 0.023404] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]--- |
|
Hi @Cuda-Chen , I checked your reply locally. I think the panic is caused by a DTB/runtime boot-mode mismatch, not by the AMO change in this PR. The key line is: The same log also lists I reproduced the same class of failure by taking a known-good That reaches the same VFS panic. With the normal external-root DTB: I get: and the same launch path boots to the Buildroot login prompt. So the likely local condition is that Maybe we can try to improve the behavior in #140. |
PR sysprog21#141 discussed a kernel panic where Linux saw 'vda' from 'virtio-blk' but still reported root device "". The manual run used a DTB generated for the legacy initramfs path, so its bootargs did not provide 'root=/dev/vda'. The command only attached '-d ext4.img' and did not pass '-i rootfs.cpio'. The default 'make check' paths already avoid this. External-root builds generate bootargs with 'root=/dev/vda' and pass '-d ext4.img'; the fakeroot fallback and explicit 'ENABLE_EXTERNAL_ROOT=0' path pass '-i rootfs.cpio' together with the initramfs DTB. Keep custom DTBs outside these default 'minimal.dtb' checks. For the built-in default-DTB cases, validate the option combination before boot so manual invocations get an actionable 'semu' error instead of reaching the guest VFS panic.
PR sysprog21#141 discussed a kernel panic where Linux saw 'vda' from 'virtio-blk' but still reported root device "". The manual run used a DTB generated for the legacy initramfs path, so its bootargs did not provide 'root=/dev/vda'. The command only attached '-d ext4.img' and did not pass '-i rootfs.cpio'. The default 'make check' paths already avoid this. External-root builds generate bootargs with 'root=/dev/vda' and pass '-d ext4.img'; the fakeroot fallback and explicit 'ENABLE_EXTERNAL_ROOT=0' path pass '-i rootfs.cpio' together with the initramfs DTB. Keep custom DTBs outside these default 'minimal.dtb' checks. For the built-in default-DTB cases, validate the option combination before boot so manual invocations get an actionable 'semu' error instead of reaching the guest VFS panic.
|
Hi @Mes0903 , Thanks for your assistance. For @shengwen-tw , |
PR sysprog21#141 discussed a kernel panic where Linux saw 'vda' from 'virtio-blk' but still reported root device "". The manual run used a DTB generated for the legacy initramfs path, so its bootargs did not provide 'root=/dev/vda'. The command only attached '-d ext4.img' and did not pass '-i rootfs.cpio'. The default 'make check' paths already avoid this. External-root builds generate bootargs with 'root=/dev/vda' and pass '-d ext4.img'; the fakeroot fallback and explicit 'ENABLE_EXTERNAL_ROOT=0' path pass '-i rootfs.cpio' together with the initramfs DTB. Keep custom DTBs outside these default 'minimal.dtb' checks. For the built-in default-DTB cases, validate the option combination before boot so manual invocations get an actionable 'semu' error instead of reaching the guest VFS panic.
PR sysprog21#141 discussed a kernel panic where Linux saw 'vda' from 'virtio-blk' but still reported root device "". The manual run used a DTB generated for the legacy initramfs path, so its bootargs did not provide 'root=/dev/vda'. The command only attached '-d ext4.img' and did not pass '-i rootfs.cpio'. The default 'make check' paths already avoid this. External-root builds generate bootargs with 'root=/dev/vda' and pass '-d ext4.img'; the fakeroot fallback and explicit 'ENABLE_EXTERNAL_ROOT=0' path pass '-i rootfs.cpio' together with the initramfs DTB. Keep custom DTBs outside these default 'minimal.dtb' checks. For the built-in default-DTB cases, validate the option combination before boot so manual invocations get an actionable 'semu' error instead of reaching the guest VFS panic.
Overview
Do not commit the AMO destination register before the store succeeds.
AMO_OPwroterdbefore confirming thatmmu_store()succeeded. If the store raised a fault, such as a COW/page fault, the destination register could be committed even though the guest kernel would handle the fault and retry the same instruction.This patch delays the
rdwrite until aftermmu_store()returns andvm->erroris known to be clear.Problem Statement
Guest GDB can hang for:
gdb -q -batch -ex "set debuginfod enabled off" -ex run --args /bin/trueAI-agent investigation reduced the hang to GDB's default worker-thread path and identified that glibc's malloc at fork unlock path was failing to release its lock:
At that point,
a4points at glibc malloc'slist_lock,a5is the value to store (0, meaning unlocked), and the current lock value is1(locked). The instruction swaps the value ina5into the lock and returns the old lock value back ina5.On the broken path, single-stepping showed that
a5still receives the old lock value, but the store did not clear the lock:The underlying issue is the AMO implementation:
mmu_store()can fault, for example on a COW/page fault afterfork(). Therefore, the old implementation can corrupt that register before the fault is handledFix
Compute the store value first, perform the store, check for an error, and only then commit
rd:Testing
scripts/buildroot-enable-gdb.shis a testing helper that appends the target GDB options needed to Buildroot config.Build a GDB-enabled guest:
chmod +x ./scripts/buildroot-enable-gdb.sh ./scripts/buildroot-enable-gdb.sh ./scripts/build-image.sh --all --no-ext4 ./scripts/rootfs_ext4.sh rootfs.cpio ext4.img 256 make semu -j$(nproc)Boot:
Inside the guest:
Expected behavior:
Before this patch: hangs
After this patch: exits normally with GDB_TRUE_EXIT:0
Summary by cubic
Delay the AMO destination register write until after
mmu_store()succeeds to prevent committingrdon a fault. Fixes a guest GDB hang triggered byamoswap.w.rlin glibc’s malloc lock path.AMO_OP, compute the store value, callmmu_store, checkvm->error, then writerd.rdcorruption on COW/page faults, restoring correct swap semantics and normal GDB exit.Written for commit deadf03. Summary will update on new commits.