让Thunderbolt可以使用更大的BAR
问题描述
在Xilinx 7-Series FPGA上用AXI Memory Mapped to PCI Express IP核设置了一个256M的BAR,这个BAR直接连接到主板的PCIe上可以正常进行MMIO,但将FPGA通过Thunderbolt硬盘盒+M.2转PCIe连接到Thunderbolt上却无法使用。
通过查阅dmesg
可观测到如下报错信息:
[ 246.677146] pci 0000:0c:00.0: BAR 0: no space for [mem size 0x10000000 64bit pref]
[ 246.677147] pci 0000:0c:00.0: BAR 0: failed to assign [mem size 0x10000000 64bit pref]
其中,0000:0c
这一地址便是我的FPGA,可以看出,BAR 0的256MB的地址无法被assign到物理地址空间,这就导致我们无法通过Kernel相关API或是/dev/mem
来对这个BAR进行MMIO访问。
调试过程
然后我尝试将BAR大小降低到128M,重新用JTAG烧写bitstream,然后连接Thunderbolt,然后观察dmesg
,结果如下:
[ 737.544256] pci 0000:0c:00.0: BAR 0: assigned [mem 0x6108000000-0x610fffffff 64bit pref]
可以看到,这个BAR 0被正确地分配到了物理地址空间,于是我查看了lspci -v
,果然也能看到Memory at xxxx [size=128M]
。并在sysfs对这个device进行了enable操作后,用户态通过mmap映射/dev/mem
对应的地址,也能正确完成MMIO。
0c:00.0 Memory controller: Xilinx Corporation Device 7021
Subsystem: Xilinx Corporation Device 0007
Physical Slot: 1-1
Flags: fast devsel, IOMMU group 32
Memory at 6108000000 (64-bit, prefetchable) [disabled] [size=128M]
然后,为了找到预留地址空间的根源,我查看了/proc/iomem
,相关的PCIe树结果如下:
60e0000000-612a0fffff : PCI Bus 0000:07 (Intel Corporation Thunderbolt 4 Bridge)
60e0000000-612a0fffff : PCI Bus 0000:08 (Intel Corporation Thunderbolt 4 Bridge)
60e0000000-6104ffffff : PCI Bus 0000:3e
6105000000-6129ffffff : PCI Bus 0000:0a
6108000000-6129ffffff : PCI Bus 0000:0b (Intel Corporation JHL7540 Thunderbolt 3 Bridge)
6108000000-611107ffff : PCI Bus 0000:0c
6108000000-610fffffff : 0000:0c:00.0 (Xilinx Corporation Device 7021)
6111100000-61111fffff : PCI Bus 0000:24 (Intel Corporation JHL7540 Thunderbolt 3 USB Controller)
6111200000-61220fffff : PCI Bus 0000:25
612a000000-612a0fffff : PCI Bus 0000:09
612a000000-612a03ffff : 0000:09:00.0 (USB controller: Intel Corporation Thunderbolt 4 NH)
612a000000-612a03ffff : thunderbolt
612a040000-612a040fff : 0000:09:00.0
然后,我尝试了拔出Thunderbolt线,整个/proc/iomem
变成了这样:
60e0000000-612a0fffff : PCI Bus 0000:07 (Intel Corporation Thunderbolt 4 Bridge)
60e0000000-612a0fffff : PCI Bus 0000:08 (Intel Corporation Thunderbolt 4 Bridge)
60e0000000-6104ffffff : PCI Bus 0000:3e
6105000000-6129ffffff : PCI Bus 0000:0a
612a000000-612a0fffff : PCI Bus 0000:09
612a000000-612a03ffff : 0000:09:00.0
612a000000-612a03ffff : thunderbolt
612a040000-612a040fff : 0000:09:00.0
其实很显然我们可以看出,问题在于给每一个端口都只分配了576MB内存(0x6129ffffff-0x6108000000
),结果这些内存实际分配到一个设备的Bus却只有144.5M了(0x611107ffff-0x6108000000
),这显然就放不下一个256MB的BAR了,我个人其实不太明白这个物理内存空间的预留逻辑,调试一度陷入僵局。
于是我来到BIOS,发现了这样的设置:
既然Reserved PMemory可以修改,且最大值可以大至4096,那么我就直接改成了4096。
(反正不是占据物理内存,只是在64bit物理地址空间中划一块地)
随后F10
保存重启,结果如下:
0c:00.0 Memory controller: Xilinx Corporation Device 7021
Subsystem: Xilinx Corporation Device 0007
Physical Slot: 1-1
Flags: fast devsel, IOMMU group 32
Memory at 6160000000 (64-bit, prefetchable) [disabled] [size=256M]
Capabilities: [40] Power Management version 3
Capabilities: [48] MSI: Enable- Count=1/1 Maskable- 64bit+
Capabilities: [60] Express Endpoint, MSI 00
Capabilities: [100] Device Serial Number 00-00-00-00-00-00-00-00
可以看到,256M
的BAR成功出现!
再次查看/proc/iomem
,结果如下:
60e0000000-61e00fffff : PCI Bus 0000:07 (Intel Corporation Thunderbolt 4 Bridge)
60e0000000-61e00fffff : PCI Bus 0000:08 (Intel Corporation Thunderbolt 4 Bridge)
60e0000000-615fffffff : PCI Bus 0000:3e
6160000000-61dfffffff : PCI Bus 0000:0a
6160000000-61dfffffff : PCI Bus 0000:0b (Intel Corporation JHL7540 Thunderbolt 3 Bridge)
6160000000-619007ffff : PCI Bus 0000:0c (Xilinx Corporation Device 7021)
6160000000-616fffffff : 0000:0c:00.0
6190100000-61901fffff : PCI Bus 0000:24
6190200000-61d00fffff : PCI Bus 0000:25
可以看到,对于整个FPGA设备的Bus有了768M物理地址空间,开个256M的BAR就不再是个问题了。