qemu进程cpu跑满不等于卡死,需先用pidstat区分%usr/%sys:若%usr>70%多为用户态死锁,%sys高伴大量ctxt/cswch则可能kvm内核线程阻塞;再用top -h和gdb查线程栈,重点识别futex_wait_queue_me、kvm_vcpu_block或qemu_mutex_lock_impl等死锁/自旋线索。

QEMU进程CPU跑满,先确认是不是它在真忙
别急着 kill -9,QEMU 占用高不等于它“卡死”——它可能只是在做繁重的模拟(比如启动 Windows、运行 GPU passthrough),也可能是被 guest 冻住后持续自旋。关键看 %usr 和 %sys 分布:pidstat -u -p <pid> 1</pid> 持续观察。如果 %usr 长期 >70%,说明 QEMU 用户态逻辑在狂转(大概率是死锁或无限重试);如果 %sys 高且伴随大量 ctxt(上下文切换)和 cswch(自愿切换),那更可能是内核线程(如 kvm-vcpu-*)在等锁或陷入中断风暴。
查 QEMU 线程是否卡在 futex 或 pthread_mutex 上
QEMU 是多线程模型,每个 vCPU 对应一个 qemu-kvm 线程,宿主机上看到的是多个 LWP。用 top -H -p <pid></pid> 找出占用最高的线程 TID,再转成十六进制:printf "%x\n" <tid></tid>。接着用 gdb -p <pid> -ex "thread apply all bt" -ex quit</pid> 抓全栈。重点看这些线索:
- 栈顶反复出现
futex_wait_queue_me、do_futex或pthread_mutex_lock→ 表明线程在等用户态锁,大概率是 QEMU 自身锁顺序混乱导致 ABBA 死锁 - 出现大量
kvm_vcpu_block+hrtimer_start_range_ns→ guest 停在 halt 指令但 KVM 无法唤醒,常见于 misconfigured APIC timer 或中断路由错误 - 栈里有
qemu_mutex_lock_impl嵌套调用,且不同线程持有不同 mutex 后又反向请求 → 典型 QEMU 内部锁竞争,尤其在热插拔设备或 migration 场景下高发
检查 KVM 内核模块是否陷入 spinlock 循环
如果 ps 显示高 CPU 的是 kvm-vcpu-<n></n> 这类内核线程(comm 列为 kvm-vcpu-0),问题不在 QEMU 用户态,而在 KVM 子系统。此时 perf top -a 会暴露热点在 kvm_arch_vcpu_ioctl_run 或 __raw_spin_lock。常见诱因包括:
- 宿主机启用了
intel_iommu=on但 guest 使用了不兼容的 VFIO 设备,导致 IOMMU 页表更新时自旋等待 - 使用了老版本内核(
-
/proc/interrupts中对应 vCPU 的 IRQ(如IO-APIC-fasteoi)计数停滞不动,说明中断被屏蔽或未送达,vCPU 在kvm_vcpu_block里空等
临时验证:改用 -cpu host,pmu=off 启动 QEMU,关闭 PMU 支持,能绕过部分 Intel CPU 上的 KVM 锁死路径。
避免误判 iowait 和 softirq 干扰
很多人看到 %wa 高就以为是磁盘拖累,但在 QEMU 场景下要格外小心:iostat -x 1 里的 %util 接近 100% ≠ 磁盘慢,可能是 QEMU 的 AIO 线程池耗尽,所有 I/O 请求排队在用户态,导致宿主机 CPU 在 io_submit 和 epoll_wait 之间高频切换。更可靠的指标是:pidstat -d -p <pid> 1</pid> 看 QEMU 自身的读写 BPS 是否异常低,同时 cat /proc/<pid>/stack</pid> 是否卡在 io_schedule。另一个陷阱是网卡软中断:cat /proc/softirqs | grep "NET_RX" 如果某 CPU 核上数值远高于其他核,且 top 显示 ksoftirqd/<n></n> 占用高,说明 virtio-net 收包不均衡,需检查是否开启了 RPS 或设置了 virsh setvcpus --live 导致 vCPU 绑定失衡。











