如何调试KVM子系统?树莓派4上QEMU调用KVM内核流程调试疑问
调试QEMU中KVM ioctl调用的方案
问题背景
你在调试QEMU源码时,发现kvm_ioctl、kvm_vm_ioctl等函数会通过ioctl@plt切换到内核上下文,但尝试通过修改kvm.ko模块调试时,发现树莓派4(Raspbian Lite 64位)中找不到该模块,且lsmod无KVM相关条目,仅/dev/kvm存在。
为什么看不到kvm.ko?
因为你的系统中KVM是**编译进内核(built-in)**而非可加载模块,所以没有独立的kvm.ko文件,lsmod也无法列出。可以通过以下命令确认:
cat /boot/config-$(uname -r) | grep CONFIG_KVM
如果输出是CONFIG_KVM=y,说明KVM是内置内核组件;若为CONFIG_KVM=m则是可加载模块。
具体调试方案
1. 内核层面调试(内置KVM)
方案A:修改内核源码添加调试输出并重新编译
- 获取对应版本的Raspbian内核源码:
sudo apt install raspberrypi-kernel-headers # 或从官方仓库克隆源码 git clone --depth=1 https://github.com/raspberrypi/linux.git -b rpi-$(uname -r | cut -d. -f1-2).y - 进入内核源码目录,修改KVM相关代码(比如
virt/kvm/kvm_main.c中的kvm_dev_ioctl_create_vm函数),添加printk输出:printk(KERN_DEBUG "KVM_CREATE_VM called, fd: %d\n", fd); - 开启内核调试配置:
make bcm2711_defconfig # 树莓派4的配置文件 make menuconfig # 开启:Kernel hacking -> Compile-time checks and compiler options -> Compile the kernel with debug info # 保存配置后编译 make -j$(nproc) Image modules dtbs - 替换树莓派的内核镜像:
sudo cp arch/arm64/boot/Image /boot/kernel8.img sudo cp arch/arm64/boot/dts/broadcom/*.dtb /boot/ sudo cp arch/arm64/boot/dts/overlays/*.dtb* /boot/overlays/ sudo reboot - 重启后查看内核日志:
dmesg | grep KVM
方案B:使用ftrace追踪KVM调用(无需重新编译内核)
ftrace是内核自带的追踪工具,可以快速定位KVM函数调用:
- 挂载tracefs:
sudo mount -t tracefs nodev /sys/kernel/tracing - 追踪KVM的VM创建ioctl处理函数:
sudo echo kvm_dev_ioctl_create_vm > /sys/kernel/tracing/set_function sudo echo 1 > /sys/kernel/tracing/tracing_on # 运行你的QEMU测试程序 cat /sys/kernel/tracing/trace_pipe - 也可以用function_graph查看调用栈:
sudo echo function_graph > /sys/kernel/tracing/current_tracer sudo echo kvm_* > /sys/kernel/tracing/set_ftrace_filter sudo echo 1 > /sys/kernel/tracing/tracing_on # 运行QEMU后查看输出 cat /sys/kernel/tracing/trace
方案C:用gdb调试内核
- 准备:树莓派开启serial控制台,或使用gdbserver通过网络连接
- 在主机上启动gdb,加载内核符号:
gdb vmlinux # vmlinux是编译内核时生成的带符号的镜像 target remote <树莓派IP>:1234 # 假设树莓派上运行了gdbserver :1234 - 设置断点在KVM的ioctl处理函数:
b kvm_dev_ioctl_create_vm c - 运行QEMU触发调用,即可在gdb中调试内核上下文。
2. 用户态QEMU调试结合内核调试
- 先在QEMU中设置断点,定位到
kvm_vm_ioctl(KVM_CREATE_VM)的调用处:gdb qemu-system-aarch64 b kvm_vm_ioctl c - 当触发断点后,使用
si跟进到ioctl@plt,此时切换到内核调试工具(如gdb连接内核),即可追踪内核侧的处理流程。
内容的提问来源于stack exchange,提问作者Yuv
相关产品推荐
相关产品推荐

