1、背景介绍
近期项目中采用全国产飞腾计算模块搭配一块FPGA模块(FPGA为复旦微的VU9P),实现业务数据的收发。FPGA中采用了Xilinx的XDMA IP核,飞腾计算模块中的FT2000+/64核处理器通过PEU1的一路 PCIE3.0x8与VU9P相连接,发现在飞腾上加载xilinx的xdma驱动时提示xdma驱动正常加载,但no device found。等于没有找到设备。
2、问题排查
首先确认硬件设备能否找到,输入lspci能看到设备
输入lspci -s 12:00.0 -vvv查看详细设备信息时输出如下:
[系统未激活][root@node12-0 tests]# lspci -s 11:00.0 -vvv
11:00.0 Serial controller: Xilinx Corporation Device 9018 (prog-if 01 [16450])Subsystem: Xilinx Corporation Device 0007Control: I/O- Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-Interrupt: pin A routed to IRQ 14Region 0: Memory at <unassigned> (64-bit, non-prefetchable) [virtual] [size=64K]Capabilities: [40] Power Management version 3Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-Capabilities: [48] MSI: Enable- Count=1/1 Maskable- 64bit+Address: 0000000000000000 Data: 0000Capabilities: [70] Express (v2) Endpoint, MSI 00DevCap: MaxPayload 1024 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1usExtTag+ AttnBtn- AttnInd- PwrInd- RBE+ FLReset- SlotPowerLimit 0.000WDevCtl: CorrErr- NonFatalErr- FatalErr- UnsupReq-RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+MaxPayload 512 bytes, MaxReadReq 1024 bytesDevSta: CorrErr- NonFatalErr- FatalErr- UnsupReq- AuxPwr- TransPend-LnkCap: Port #0, Speed 8GT/s, Width x8, ASPM not supportedClockPM- Surprise- LLActRep- BwNot- ASPMOptComp+LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk-ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-LnkSta: Speed 8GT/s (ok), Width x8 (ok)TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-DevCap2: Completion Timeout: Range BC, TimeoutDis+, NROPrPrP-, LTR-10BitTagComp-, 10BitTagReq-, OBFF Not Supported, ExtFmt-, EETLPPrefix-EmergencyPowerReduction Not Supported, EmergencyPowerReductionInit-FRS-, TPHComp-, ExtTPHComp-AtomicOpsCap: 32bit- 64bit- 128bitCAS-DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis+, LTR-, OBFF DisabledAtomicOpsCtl: ReqEn-LnkCtl2: Target Link Speed: 8GT/s, EnterCompliance- SpeedDis-Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-Compliance De-emphasis: -6dBLnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-Capabilities: [100 v1] Advanced Error ReportingUESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr-CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr+AERCap: First Error Pointer: 00, ECRCGenCap- ECRCGenEn- ECRCChkCap- ECRCChkEn-MultHdrRecCap- MultHdrRecEn- TLPPfxPres- HdrLogCap-HeaderLog: 00000000 00000000 00000000 00000000
上面显示
Region 0: Memory at <unassigned> (64-bit, non-prefetchable) [virtual] [size=64K]
也就是bar空间无法分配,此时输入dmesg 查看驱动加载异常日志,显示
[ 1203.426451] xdma v2017.0.45
[ 1203.426560] xdma 0000:11:00.0: can't enable device: BAR 0 [mem size 0x00010000 64bit] not assigned
[ 1203.426572] xdma: probe of 0000:11:00.0 failed with error -1
[ 1203.426597] xdma 0000:12:00.0: can't enable device: BAR 0 [mem size 0x00010000 64bit] not assigned
[ 1203.426603] xdma: probe of 0000:12:00.0 failed with error -1
[ 1255.253522] xdma v2017.0.45
[ 1255.253629] xdma 0000:11:00.0: can't enable device: BAR 0 [mem size 0x00010000 64bit] not assigned
[ 1255.253640] xdma: probe of 0000:11:00.0 failed with error -1
[ 1255.253665] xdma 0000:12:00.0: can't enable device: BAR 0 [mem size 0x00010000 64bit] not assigned
[ 1255.253671] xdma: probe of 0000:12:00.0 failed with error -1
也提示找不到设备的原因为bar空间probe失败了。
可以判断直接原因是 BAR0 根本没有被分配物理地址。
在chatgpt上把日志信息贴出后,建议解决思路如下:
结合情况分析
硬件侧 (FPGA/bitstream)
这个设备是
Xilinx XDMA
IP 导出的 PCIe Endpoint。如果 bitstream 没有正确启用 BAR0(或者 BAR 大小配置和驱动不一致),内核扫描 PCIe 配置空间时不会分配内存资源。
你可以用
setpci -s 11:00.0 BASE_ADDRESS_0
查看 BAR0 的原始值,确认是不是0x00000000
。BIOS/UEFI 设置
如果 BAR 是 64-bit,需要 BIOS 支持并开启 Above 4G Decoding / Large BAR support,否则 BIOS 不会给它分配地址。
典型症状就是
lspci
里显示<unassigned>
。内核资源分配
Linux 看到 BAR0 需要内存,但 BIOS 没分配,就不会启用设备。
内核有时候能“重新分配”资源,可以尝试在 grub 加参数:
pci=realloc
pci=assign-busses
然后
update-grub && reboot
。
其实针对2和3点,因为使用同一个模块与另一个FPGA模块(复旦微的V7)测试xdma没有问题,可以排除。第1点在FPGA工程师检查和确认下也进行了排除。
最后排查发现,当FPGA 的XDMA IP核启动慢时,将导致BAR0空间无法分配,chatgpt也给出了解释:
短答:会的。
如果 FPGA(含 XDMA IP)在主机进行 PCIe 枚举/资源分配时还没就绪,BIOS/固件无法读取有效的 BAR 配置,就不会给 BAR 分配 MMIO 地址;等你后面 bitstream 才起来时,设备已经“错过了”最初的分配时机,于是出现你看到的BAR 0 ... not assigned
,驱动 probe 失败。为什么会这样
PCIe 上电后主机流程是:
释放 PERST# → 链路训练到 L0 → 读配置空间(BAR size) → 分配 MMIO
。
若 XDMA 在这些步骤发生时还没配置好(如 bitstream 还没完成、user_lnk_up 还没到 L0、BAR 寄存器还未有效),主机会认为“没有/不需要内存资源”,于是不会给 BAR 地址。后面即使链路正常了,除非固件/OS重新分配,否则lspci
里就会一直是<unassigned>
,驱动就启用不了设备。你可以怎么解决(两条路线)
A. 从硬件/时序上根治
保证“配置先于枚举”
把 bitstream 存在板载 SPI-Flash,随上电先完成 FPGA 配置;
或者用 CPLD/MCU 延迟释放 PERST#,直到
DONE=1
、MMCM/PLL locked
、user_lnk_up=1
(或 LTSSM=L0)再放开。检查 XDMA 配置
PF0 BAR0 启用且大小与驱动期望一致(常见 64 KB AXI-Lite 控制空间)。
不要改动到导致 BAR 为 0 的设置。
主板 BIOS 设置
打开 Above 4G Decoding / Large BAR,避免 64-bit BAR 分配失败。
若插槽支持热插拔/下行端口复位,确保启用。
B. 运行时的补救(设备已“错过”枚举)
成功与否取决于上游 Root Port/桥是否支持热插拔/热复位以及系统是否允许 OS 侧重新分配资源。
尝试 OS 侧重新分配资源
临时一次性:
echo 1 | sudo tee /sys/bus/pci/rescan
若仍不分配,先“移除再扫描”:
echo 1 | sudo tee /sys/bus/pci/devices/0000:11:00.0/remove echo 1 | sudo tee /sys/bus/pci/rescan
仍失败,给内核加参数让其强制重新分配(下次重启生效):
pci=realloc
对上游端口做热复位(可选、谨慎)
如果内核导出了 reset 接口:
echo 1 | sudo tee /sys/bus/pci/devices/0000:<UPSTREAM_PORT>/reset
或通过 Secondary Bus Reset(依平台而定,可能影响同总线其他设备)。
如果这些补救都不行,基本就只能回到 A 路线:保证 FPGA 在 BIOS/OS 枚举时已经就绪。
不过由于飞腾2000+ 64核不支持PCIE热插拔,于是重新reset或先移除再扫描无法解决该问题
在 飞腾 2000+ 这种处理器平台上,PCIe 确实没有热插拔(Hot-Plug)能力,所以不能像服务器那样靠 Root Port 做 Slot Reset,让设备重新枚举。但 remove/rescan 这类软件操作,本质上只是让内核释放并重新探测配置空间,并不是真的“热插拔”,因此是否可行要看 设备枚举时 BAR 是否已经有效。
最终解决办法是让FPGA 逻辑在飞腾计算模块枚举前加载完毕,否则只能让飞腾计算模块上电后执行reboot了。
chatgpt也产生了一个自动检测PCIE设备的脚本,供参考
#!/bin/bash
# quick_pcie_rescan_auto.sh
# 自动检测并测试 Xilinx XDMA (10ee:9018) 设备是否能在 bitstream 加载后重新分配 BAR
# 打印 BAR0 地址和大小,并检查是否有效VENDOR="10ee"
DEVICE="9018"echo ">>> 扫描 PCIe 总线,查找 Xilinx XDMA 设备 ($VENDOR:$DEVICE) ..."
DEVICES=$(lspci -Dnnd ${VENDOR}:${DEVICE} | awk '{print $1}')if [ -z "$DEVICES" ]; thenecho "未发现 Xilinx XDMA 设备 ($VENDOR:$DEVICE)。"exit 1
fifor DEV in $DEVICES; doecho "------------------------------------------"echo ">>> 处理设备: $DEV"SYSFS_DEV="/sys/bus/pci/devices/0000:$DEV"if [ ! -d "$SYSFS_DEV" ]; thenecho "设备 $DEV 的 sysfs 路径不存在,跳过。"continuefiecho ">>> 移除设备 $DEV ..."echo 1 > "$SYSFS_DEV/remove"echo ">>> 重新扫描 PCIe 总线 ..."echo 1 > /sys/bus/pci/rescanecho ">>> 查看 BAR0 分配情况:"REGION_INFO=$(lspci -s $DEV -vvv | grep -A5 "Region 0")echo "$REGION_INFO"# 解析 BAR0 大小 (size=字段)BAR0_SIZE=$(echo "$REGION_INFO" | grep -oP "size=\K\S+")if [ -n "$BAR0_SIZE" ]; thenecho "BAR0 大小: $BAR0_SIZE"elseecho "BAR0 大小: 未检测到"fiecho ">>> 读取 BAR0 原始寄存器值:"BAR0_HEX=$(setpci -s $DEV BASE_ADDRESS_0)echo "BAR0 raw value = 0x$BAR0_HEX"# 检查 BAR0 是否有效if [[ "$BAR0_HEX" == "00000000" || "$BAR0_HEX" == "ffffffff" ]]; thenecho "!!! 警告: FPGA BAR0 未导出 (值=$BAR0_HEX)"echo ">>> 可能原因: FPGA bitstream 未配置 BAR0 或启动时序太慢,需检查硬件侧。"elseecho ">>> FPGA BAR0 看起来有效 (值=$BAR0_HEX)"fi
done
输出示例如下:
>>> 查看 BAR0 分配情况:
Region 0: Memory at 91c00000 (64-bit, non-prefetchable) [size=64K]
BAR0 大小: 64K
>>> 读取 BAR0 原始寄存器值:
BAR0 raw value = 0x91c00004
>>> FPGA BAR0 看起来有效 (值=0x91c00004)