背景
在 PVE (Proxmox VE) 中使用 PCI 直通(Passthrough)时,设备会被绑定到 vfio-pci 驱动以供虚拟机独占使用。但当虚拟机停止后,宿主机无法再使用该设备。
本文以 ASMedia ASM1061 SATA 控制器 为例,演示如何在 vfio-pci 和 ahci 之间手动切换,并通过 hookscript 实现自动化。
一、查看当前驱动绑定
lspci -k -s 06:00.0
输出示例:
06:00.0 SATA controller: ASMedia Technology Inc. ASM1061/ASM1062 Serial ATA Controller (rev 02)
Subsystem: ASUSTeK Computer Inc. ASM1061/ASM1062 Serial ATA Controller
Kernel driver in use: vfio-pci
Kernel modules: ahci
Kernel driver in use 显示当前使用的驱动,Kernel modules 列出该设备可用的驱动模块。
二、手动切换驱动
2.1 解绑 vfio-pci
有两种方式,效果相同:
# 方式一:通过设备路径解绑
echo 0000:06:00.0 > /sys/bus/pci/devices/0000:06:00.0/driver/unbind
# 方式二:通过驱动路径解绑
echo 0000:06:00.0 > /sys/bus/pci/drivers/vfio-pci/unbind
验证解绑成功——Kernel driver in use 行消失:
lspci -k -s 06:00.0
06:00.0 SATA controller: ASMedia Technology Inc. ASM1061/ASM1062 Serial ATA Controller (rev 02)
Subsystem: ASUSTeK Computer Inc. ASM1061/ASM1062 Serial ATA Controller
Kernel modules: ahci
2.2 绑定到 ahci
echo 0000:06:00.0 > /sys/bus/pci/drivers/ahci/bind
验证绑定成功:
lspci -k -s 06:00.0
06:00.0 SATA controller: ASMedia Technology Inc. ASM1061/ASM1062 Serial ATA Controller (rev 02)
Subsystem: ASUSTeK Computer Inc. ASM1061/ASM1062 Serial ATA Controller
Kernel driver in use: ahci
Kernel modules: ahci
至此,宿主机已重新接管该 SATA 控制器。
三、使用 Hookscript 自动切换
手动切换太麻烦?PVE 支持为虚拟机绑定 hookscript,在 VM 启动/停止时自动执行脚本。
3.1 创建脚本
PVE 的 hookscript 存放在 /var/lib/vz/snippets/ 目录下,支持 Bash、Perl、Python 等格式。
nano /var/lib/vz/snippets/bind-ahci.sh
写入以下内容(将 100 替换为你的虚拟机 ID):
#!/bin/bash
# PVE hookscript: ASM1061 驱动自动切换
# 用法:虚拟机启动前绑定 vfio-pci,停止后归还 ahci
vmid=$1
phase=$2
# 只处理指定虚拟机
if [ "$vmid" != "100" ]; then
exit 0
fi
case "$phase" in
pre-start)
# 启动前:从宿主机收回设备,交给虚拟机
echo 0000:06:00.0 > /sys/bus/pci/drivers/ahci/unbind 2>/dev/null
echo 0000:06:00.0 > /sys/bus/pci/drivers/vfio-pci/bind 2>/dev/null
logger "Hook: ASM1061 → vfio-pci (VM $vmid starting)"
;;
post-stop)
# 停止后:从虚拟机归还设备给宿主机
echo 0000:06:00.0 > /sys/bus/pci/drivers/vfio-pci/unbind 2>/dev/null
echo 0000:06:00.0 > /sys/bus/pci/drivers/ahci/bind 2>/dev/null
logger "Hook: ASM1061 → ahci (VM $vmid stopped)"
;;
esac
exit 0
3.2 赋予执行权限
chmod +x /var/lib/vz/snippets/bind-ahci.sh
3.3 绑定到虚拟机
qm set 100 --hookscript local:snippets/bind-ahci.sh
说明:local:snippets/bind-ahci.sh 是 PVE 存储卷路径语法,local 对应 /var/lib/vz。如果你的环境没有 local 存储,可通过 pvesm status 确认,或在 /etc/pve/storage.cfg 中添加。
3.4 验证配置
qm config 100 | grep hookscript
输出应为:
hookscript: local:snippets/bind-ahci.sh
四、移除 Hookscript
不再需要自动切换时,按顺序清理:
# 1. 取消虚拟机的 hookscript 绑定
qm set 100 --delete hookscript
# 2. 验证已移除(输出为空即成功)
qm config 100 | grep hookscript
# 3. 可选:删除脚本文件
rm /var/lib/vz/snippets/bind-ahci.sh
注意:先取消绑定再删除脚本,避免 PVE 找不到脚本而报错。