PVE Win11 虚拟机音画卡顿排障:从中断集中到 USB 控制器直通

背景

这次问题发生在一台 PVE 宿主机上的 Win11 虚拟机。现象不是单一设备异常,而是更接近系统级延迟毛刺:

  • USB 声卡偶现 1 到 2 秒断音。
  • 部分时候画面也同步掉帧或卡顿。
  • Win11 默认使用 VirtIO 网卡,偶尔也会出现网络断开的体感。
  • USB 网卡反而相对稳定。

硬件环境里有几个对实时音频比较敏感的因素:

  • AMD Ryzen 7 3700X,8 核 16 线程,双 CCX 架构。
  • Win11 虚拟机分配 16 vCPU。
  • RTX 3060 Ti PCIe 直通。
  • USB 声卡、键盘、鼠标、蓝牙最初使用 PVE 的单 USB 设备转发。
  • PVE 物理网卡是 Realtek RTL8111/8168,VirtIO 网卡桥接到 vmbr0

这篇文章记录排查和修复过程。重点不是给出一套万能配置,而是展示如何先验证证据,再决定动哪一刀。

第一轮证据:中断集中

先看宿主机中断分布:

1
cat /proc/interrupts

当时最明显的问题是 03:00.0 xhci_hcd 的中断高度集中:

1
IRQ 52  0000:03:00.0 xhci_hcd  -> CPU2

这个 USB 控制器累计中断已经超过 27 亿次,而且有效亲和性落在单个逻辑核心上。短时间采样里,它仍然保持每秒数百次中断。

同时还有几个重要现象:

1
2
3
4
IRQ 41  nic0                  -> CPU14
IRQ 72 vfio-intx 29:00.1 -> NVIDIA HDMI Audio
IRQ 73 vfio-intx 2b:00.4 -> AMD HDA
IRQ 91 vfio-msi 29:00.0 -> NVIDIA GPU

其中 vfio-intx 值得注意。INTx 是传统引脚中断,延迟和共享风险都比 MSI/MSI-X 更高。虽然采样时它们不一定持续增长,但在音频、显卡直通这种实时链路里,仍然是潜在风险点。

第二轮证据:不是所有断音都是 USB 断开

排查时做了实时日志抓取:

1
journalctl -k -f -n0 | egrep -i 'usb|xhci|reset|disconnect|error -71|vfio|virtio|NETDEV'

在某个 90 秒窗口里,声音毛刺持续出现,但内核没有新增 USB reset/disconnect。这说明当时的声音问题更像是调度延迟或 DPC 延迟,并不是每次都伴随设备断开。

但再往前后看日志,又能看到明确的 USB 层问题:

1
2
3
4
5
6
usb 1-2.1: USB disconnect
usb 1-2.1: Product: JM6PRO (CX31993+MAX97220)
usb 1-2.3: reset full-speed USB device
usb 1-2.2: reset full-speed USB device
usb 1-8: reset full-speed USB device
r8152-cfgselector 3-1: reset high-speed USB device

也就是说,这台机器同时存在两类问题:

  • 实时链路延迟毛刺:表现为音画同步卡顿,不一定有 USB 断开日志。
  • USB 链路 reset:表现为声卡、键鼠、蓝牙、USB 网卡等设备被宿主机重新枚举。

这两类问题会互相放大,但不能混为一个原因。

第三轮证据:VirtIO 网卡没有在宿主侧报错

Win11 默认使用 VirtIO 网卡,宿主机对应接口是 tap103i0。采样时看宿主侧统计:

1
ip -s link show tap103i0

结果是:

1
2
3
4
RX errors: 0
TX errors: 0
RX dropped: 0
TX dropped: 0

PVE 的物理口 nic0 也没有看到 link down/up。因此网络问题没有在这轮抓到硬件链路证据,暂时按“可能受中断调度和虚拟网卡单队列影响”处理,而不是直接认定物理网口故障。

先做低风险修复:启用 irqbalance

宿主机上最初没有安装 irqbalance。先做低风险修复:

1
2
apt-get install -y irqbalance
systemctl enable --now irqbalance

并临时把关键 IRQ 分散到不同核心验证:

1
2
3
4
5
6
echo 5  > /proc/irq/52/smp_affinity_list   # 03:00.0 xhci
echo 7 > /proc/irq/41/smp_affinity_list # nic0
echo 10 > /proc/irq/61/smp_affinity_list # 2b:00.3 xhci
echo 13 > /proc/irq/72/smp_affinity_list # 29:00.1 HDMI Audio INTx
echo 15 > /proc/irq/73/smp_affinity_list # 2b:00.4 HDA INTx
echo 12 > /proc/irq/91/smp_affinity_list # 29:00.0 GPU

这一步之后,音频断续频率有所下降,但没有完全消失。说明方向有效,但不是最终解法。

经验:irqbalance 可以降低明显的单核心热点,但如果设备本身只有一个 MSI 向量,或者仍然通过宿主机转发 USB 请求,它无法把单个中断真正拆成多队列。

关键判断:单 USB 设备转发不是实时音频的好方案

最初 Win11 配置里 USB 设备是这样的:

1
2
3
4
5
usb0: host=1-2.2       # 鼠标
usb1: host=8087:0029 # 蓝牙
usb2: host=1-2.3 # 键盘
usb3: host=1-2.1 # JM6PRO USB 声卡
usb4: host=3-1 # RTL8153 USB 网卡

这类 usb-host 单设备转发有一个问题:USB 中断先由 PVE 宿主机的 xhci_hcd 处理,再由 QEMU 转给虚拟机。实时音频路径会经过宿主机调度、QEMU、客户机驱动三层。

对键盘鼠标来说通常可以接受;对 USB 声卡和手柄音频来说,就很容易暴露延迟毛刺。

查看 USB 拓扑:

1
lsusb -t

可以看到 JM6PRO、键盘、鼠标、蓝牙都挂在同一个控制器 0000:03:00.0 对应的 Bus 1/2 上。再看 IOMMU 分组:

1
2
3
4
5
for d in 0000:03:00.0 0000:03:00.1 0000:03:00.2; do
g=$(basename "$(readlink /sys/bus/pci/devices/$d/iommu_group)")
echo "$d group $g"
ls /sys/kernel/iommu_groups/$g/devices/
done

结果显示 0000:03:00.0 是独立 IOMMU 分组,可以单独直通:

1
0000:03:00.0 group 15

于是最终选择把整颗 xHCI 控制器直通给 Win11,而不是继续让 PVE 转发单个 USB 设备。

最终修复:整 USB 控制器 PCIe 直通

先关闭 Win11 虚拟机,并备份配置:

1
2
cp -a /etc/pve/qemu-server/103.conf \
/root/pve-vm-config-backups/103.conf.before-usb-controller-passthrough.$(date +%Y%m%d-%H%M%S)

然后删除原有的单 USB 设备转发:

1
2
3
4
qm set 103 --delete usb0
qm set 103 --delete usb1
qm set 103 --delete usb2
qm set 103 --delete usb3

添加整 USB 控制器直通:

1
qm set 103 --hostpci4 0000:03:00.0,pcie=1

保留 usb4: host=3-1,因为 RTL8153 USB 网卡在另一个控制器上,暂时不动。

最终关键配置变成:

1
2
hostpci4: 0000:03:00.0,pcie=1
usb4: host=3-1

启动虚拟机后,宿主机侧确认 03:00.0 已经交给 VFIO:

1
lspci -nnk -s 03:00.0

输出里应看到:

1
Kernel driver in use: vfio-pci

再看宿主机 USB:

1
lsusb -t

原来的 Bus 1/2 不再出现在 PVE 宿主机里,说明整颗控制器已经由 Win11 接管。

Win11 侧能看到:

  • AMD USB 3.10 eXtensible Host Controller
  • JM6PRO (CX31993+MAX97220)
  • 键盘、鼠标、蓝牙等挂在这颗控制器下的设备

此后声音表现恢复正常。

启动警告怎么理解

启动时出现过类似警告:

1
Cannot reset device 0000:03:00.0, depends on group 17 which is not owned.

这类警告不等于直通失败。这里 03:00.0 是芯片组 USB 控制器,它的 reset 依赖上游桥或同芯片组路径;PVE 无法完整拥有相关依赖,所以提示 reset 不完整。

只要满足以下条件,就可以先观察:

  • VM 能正常启动。
  • 03:00.0 已绑定到 vfio-pci
  • Win11 能看到 AMD USB 控制器。
  • USB 设备在 Win11 内状态正常。
  • 宿主机不再看到 Bus 1/2 设备。

不要为了消除这条警告盲目开启 pcie_acs_override,也不要把承载宿主机网卡或其他关键设备的桥一起直通。

为什么没有直接做这些操作

排障过程中有人可能会建议一口气做很多优化,例如:

  • 把 Win11 从 16 vCPU 缩到 4 核。
  • 关闭 C-state、ASPM 并重启宿主机。
  • 给 QEMU 设置实时优先级 chrt -f 99
  • 开启 pcie_acs_override
  • 修改大量 Windows 音频服务和注册表。

这些方向并非都错,但不应该同时做。原因很简单:改动太多会失去因果关系,也会提高回滚成本。

这次实际采取的顺序是:

  1. 先确认中断集中和 USB reset 是真实存在的。
  2. 先用 irqbalance 做低风险调度修复。
  3. 观察到问题频率降低但未消失。
  4. 再切换 USB 架构,把实时 USB 音频从宿主机转发改为整控制器直通。

这样每一步都有证据,也有回滚路径。

回滚方法

如果整 USB 控制器直通后出现启动问题,可以关机后回滚:

1
2
3
4
5
qm set 103 --delete hostpci4
qm set 103 --usb0 host=1-2.2
qm set 103 --usb1 host=8087:0029
qm set 103 --usb2 host=1-2.3
qm set 103 --usb3 host=1-2.1

也可以直接从备份恢复 /etc/pve/qemu-server/103.conf,但恢复前要确认虚拟机已经关机。

后续仍需关注的点

这次主要修复 USB 音频链路。还有几个后续优化方向:

  • 在 Win11 里用 LatencyMon 检查 nvlddmkm.sysusbaudio.systcpip.sysstorport.sys
  • 用 MSI Utility 给 NVIDIA HDMI Audio 等设备开启 MSI,减少 vfio-intx
  • 检查 Win11 内存完整性 HVCI、USB 选择性暂停、PCIe 链路状态电源管理。
  • 如果 VirtIO 网卡仍偶发断开,再考虑给 net0 加 multiqueue/RSS,而不是先怀疑物理网线。
  • 如果音画仍同步卡顿,再考虑 CPU 亲和性、CCX 绑定、C-state/ASPM 这类更大的宿主机级修改。

总结

这次故障的关键经验是:音频断续不一定只看音频设备,画面同步卡顿也不一定只看显卡。虚拟化环境里,USB、GPU、网卡、CPU 调度和中断亲和性会叠在一起。

最终有效的修复不是某个“万能参数”,而是先用证据把问题拆开:

  • /proc/interrupts 确认中断热点。
  • journalctl -k 确认 USB reset。
  • lsusb -t 确认设备拓扑。
  • IOMMU group 确认能否安全直通。
  • usb-host 单设备转发切到整 xHCI 控制器 VFIO 直通。

对 USB 声卡、手柄音频这类实时设备,整控制器直通通常比单设备转发稳定得多。