0x00 序

AMD EPYC 7282 + H11SSL-i SATA控制器直通失败(实际上好像ryzen也可能有这个问题)

单独记录这个”简单”的直通问题, 以及整个直通SATA爬坑的过程.

0x01 问题

在正常安装完成PVE后, 本来是最简单的直通SATA控制器环节, 反而在进入TrueNAS以及任何Linux环境都会报错:
ata22: softreset failed (1st FIS failed)

我的环境是EPYC 7282 + H11SSL-i, lspci可以看到4个SATA控制器, 其中86:00,87:00没有使用, 所以有效的是43:00 44:00这两个

0x02 排查第一天

起初怀疑是SFF-8643线的问题,但是实际上硬盘在PVE环境中运行正常, 所以应该是直通的过程中出现了问题, 最开始的怀疑是IOMMU分组有问题,分组如下:

1
2
3
4
5
root@pve00:~# for d in /sys/kernel/iommu_groups/*/devices/*; do n=${d#*/iommu_groups/*}; n=${n%%/*}; printf 'IOMMU Group %s ' "$n"; lspci -nns "${d##*/}"; done|grep 44:00
IOMMU Group 79 44:00.0 SATA controller [0106]: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI mode] [1022:7901] (rev 51)
root@pve00:~# for d in /sys/kernel/iommu_groups/*/devices/*; do n=${d#*/iommu_groups/*}; n=${n%%/*}; printf 'IOMMU Group %s ' "$n"; lspci -nns "${d##*/}"; done|grep "Group 79"
IOMMU Group 79 44:00.0 SATA controller [0106]: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI mode] [1022:7901] (rev 51)

如果是分组有问题, 控制器连接的Bridge被分走了, 导致失败? 所以刚开始是测试了一下ACS, 在配置了pcie_acs_override=downstream后还是不能直通,那应该不是这个原因.

0x03 排查第二天

(实际上这次排查除了学到了点pci相关的命令, 没有用处)

继续排查(实际上是第二天了), 如果是被host占用了,那我一开始就直接不使用这个控制器呢?这个帖子的帮助下,我看到了点希望(??), 配置了这些:

1
2
3
4
5
6
GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt pcie_acs_override=downstream"

root@pve00:~# cat /etc/modprobe.d/test.conf
options vfio-pci ids=1022:7901
softdep ahci pre: vfio-pci
softdep ahci pre: vfio-pci

帖子的楼主说他没有生效,但是我实际是生效了的:

1
2
3
4
5
root@pve00:~# lspci -k -s 44:00
44:00.0 SATA controller: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI mode] (rev 51)
Subsystem: Super Micro Computer Inc FCH SATA Controller [AHCI mode]
Kernel driver in use: vfio-pci
Kernel modules: ahci

可以看到我最终在系统使用AHCI之前先加载了vfio驱动, 但是测试发现没有解决问题, 还是有报错softreset failed, google上看了几个,都不是我这种情况

0x04 排查第三天, 解决

在前面测试重置驱动的过程中发现了个问题, 虚拟机是使用了vfio-pci的驱动, 那是不是这个有什么特殊配置呢, 关键词vfio, softreset failed, google到了两个非常有帮助的社区讨论,其中还有个正在进行中的帖子:

大概看了这两个帖子以及帖子带过去的几个链接, 感觉就是vfio-pci驱动在把pcie给虚拟机使用, 进行重置的时候, 重置的方法不对.

旧版本内核,可以通过修改源码重新编译的方法来用, 不过最新的PVE带的5.15内核支持不同方法来重置pci:https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
修改reset_method可以调整支持的reset方法,和方法顺序

这次直接测试一下:

1
2
3
4
5
6
7
8
cat /sys/bus/pci/devices/0000:44:00/reset_method
flr bus

# 说明目前是用的flr重置, 换成bus来试试

echo "bus" > /sys/bus/pci/devices/0000:44:00/reset_method

# 这样就是让44:00的设备重置pci时使用bus方法

直通给虚拟机, 成功了. Host和VM读取都正常!!

接下来, 怎么让每次PVE开机都自动禁用flr了, 在pve-guests启动前(这样配置不行, 参考最新VM启动前的hook脚本:hook配置), 先启动一个脚本, 来处理各种虚拟机启动前需要做的事情, 包括后面的SR-IOV

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 添加ExecStartPre
root@pve00:/usr/local/bin# vim /usr/lib/systemd/system/pve-guests.service
...
ExecStartPre=-/usr/local/bin/pve-pre-hook.sh
...


# 脚本
root@pve00:/usr/local/bin# vim pve-pre-hook.sh
#!/bin/bash

# SATA controller reset_method
#echo "bus" > /sys/bus/pci/devices/0000:44:00/reset_method
lspci -n|grep 1022:7901 |awk '{print $1}' | while read _id; do echo "set reset_method for PCI ${_id}"; echo "bus" > /sys/bus/pci/devices/0000:$_id/reset_method;done

# SR-IOV

# sleep
sleep 20


root@pve00:/usr/local/bin# chmod a+x pve-pre-hook.sh

0x05 总结

实际上到现在具体的原理和原因我都不太清楚, 只知道是reset导致的问题, 中间走了非常多弯路. 包括但不限于使用Esxi来直通印证问题点(Esxi支持reset methods: flr, d3d0, link, bridge, default), 查看了几个当时觉得有用实际完全不同的帖子, 等等等等…

学无止境~

0x06 参考

google了非常多帖子, 有效的其实挺多的, 把重要的列一下吧:

相关的:

遇到的比较有意义的帖子:

评论