基于LS1043的Linux PCI驱动内存访问错误处理问询
问题解答
AER未捕获错误的排查方向
这大概率是配置问题,从这几个维度检查:
- 内核编译:确认开启
CONFIG_PCIEAER和CONFIG_PCI_ERROR_RECOVERY选项 - FPGA端配置:检查PCIe配置空间里的AER相关寄存器(比如Uncorrectable Error Mask),是否放开了事务超时错误的上报权限
- 平台固件:LS1043的UBoot/设备树里要确保PCIe控制器的AER功能已启用,部分平台需要设置专门的启动参数或设备树节点
无需范围检查处理IO访问错误的方案
Linux内核提供了两种靠谱的方式,不用提前做地址范围检查就能避免段错误:
1. 使用安全IO访问函数
用probe_kernel_read()/probe_kernel_write()替代普通的ioreadX()/iowriteX(),这两个函数会在访问出错时返回错误码,而不是触发Oops或段错误。示例代码:
u32 reg_val; // io_addr是ioremap得到的BAR0虚拟地址 int ret = probe_kernel_read(®_val, (void __user __force *)io_addr, sizeof(reg_val)); if (ret) { // 处理访问失败,比如返回EIO给上层 return ret; } // 正常处理reg_val
注意这里的强制转换是因为函数原本设计用于用户空间地址,但内核虚拟地址(包括ioremap后的MMIO地址)也可以用。
2. 配置AER并注册错误回调
如果把AER配置正确,当FPGA触发事务超时,PCIe控制器会发送AER中断,内核会通知驱动处理。你可以在驱动里注册错误回调函数:
static pci_ers_result_t fpga_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { // 这里做错误恢复,比如复位FPGA、重新初始化寄存器等 return PCI_ERS_RESULT_RECOVERED; } static struct pci_error_handlers fpga_err_handler = { .error_detected = fpga_error_detected, // 按需实现mmio_enabled、slot_reset等其他回调 }; // 在驱动初始化里添加 pci_enable_pcie_error_reporting(pdev); pci_set_error_handlers(pdev, &fpga_err_handler);
这个方法的前提是AER必须配置到位,否则回调不会被触发。
内容的提问来源于stack exchange,提问作者billy_herrington
相关产品推荐
相关产品推荐

