011、PCIE地址空间:内存、IO与配置
PCIE地址空间内存、IO与配置最近帮同事排查一个PCIE设备异常的问题现象很典型系统能识别到设备但驱动一读写寄存器就报错。用lspci看了一眼BAR空间分配正常但访问时总是产生Completion Abort。最后发现是配置空间里某个BAR的地址类型设错了——设备厂商原本设计的是内存空间硬件工程师手滑配成了IO空间。今天我们就来彻底理清PCIE的三种地址空间这类问题你以后一眼就能看穿。从一次硬件访问说起当你写一句简单的mmio_read32(bar0 0x10)时CPU到底做了什么在x86体系下这个地址如果落在PCIE的内存地址区域CPU会生成一个Memory Read TLP事务层包通过PCIE拓扑路由到目标设备。设备返回数据完成一次访问。但如果这个地址被错误地标记为IO空间而设备实际是内存映射的整个握手协议就全乱了。理解地址空间类型就是理解PCIE通信的地基。三种地址空间详解内存地址空间Memory Space这是最常用、性能最好的空间。设备通过BARBase Address Register申请一段内存区域系统统一编址后这段内存就像物理内存一样可以直接用load/store指令访问。现代PCIE设备几乎都用这个空间。关键点在于内存空间支持64位地址、支持预取Prefetchable还能设置内存类型如32位非预取、64位预取等。配置时一定要检查BAR的类型位硬件设计错了软件根本救不回来。IO地址空间I/O Spacex86架构的历史遗产现在很少用。IO空间独立于内存编址需要专门的in/out指令访问。PCIE规范保留它主要是为了兼容老设备。最大缺点只有32位地址不支持预取访问效率低。如果你的设备是新的千万别选这个模式。我见过有人抄老代码把BAR配成IO空间结果在ARM平台上直接崩了——ARM压根不支持IO指令。配置空间Configuration Space这是PCIE的“元空间”每个设备都有256字节的标准配置空间Type0或4096字节的扩展空间Type1。配置空间不是通过内存地址访问的而是通过总线/设备/功能号BDF加上偏移量用特定的配置事务访问。在Linux里你用pci_read_config_dword这类API操作的就是这里。配置空间存放着设备ID、BAR信息、中断引脚等关键信息系统枚举设备时就是靠读这里识别硬件的。配置空间的那些坑配置空间前64字节是标准头区域必须实现。偏移0x00是厂商ID和设备ID——这里有个坑有些FPGA做的原型芯片ID没配对系统枚举时直接认成未知设备。偏移0x10开始是6个BAR寄存器每个BAR决定了一块地址空间的属性。看BAR寄存器最低几位Bit0永远为1表示BAR有效Bit1-200表示内存空间01表示IO空间仅BAR0支持Bit3内存空间专用0表示32位地址1表示64位地址Bit4内存空间专用0表示不可预取1表示可预取举个例子如果你读到BAR的值是0xFFFF0004拆开看最低位1有效bit1-2是00说明是内存空间bit3是0说明32位地址bit4是0表示不可预取。那么这块空间就是32位非预取内存空间。预取属性搞错会导致CPU缓存行为异常数据一致性出问题。驱动开发中的实战经验写PCIE驱动时第一件事就是正确映射BAR空间。用pci_iomap()函数内核会根据BAR类型自动选择映射方式。千万别自己手动算地址——我见过有人直接ioremap()物理地址结果IO空间和内存空间处理方式不同导致访问错乱。配置空间访问要用标准的PCI API比如pci_read_config_word()。直接怼物理地址在某些架构上根本行不通。还有修改配置空间要小心动错了地方可能让设备直接失联。特别是命令寄存器Offset 0x04的IO空间使能位和内存空间使能位一般保持默认就好别手贱去关。枚举设备时注意桥设备的配置空间类型是Type1端点设备是Type0。Type1有总线号寄存器系统靠这个展开PCIE树。如果你在搞FPGA开发仿真时一定要把配置空间类型设对不然软件栈枚举会卡住。给工程师的几条硬核建议硬件设计阶段就把BAR空间规划清楚能用内存空间就别用IO空间需要大地址或预取特性就选64位预取内存空间。硬件工程师和驱动工程师要对齐这张表。调试时先用lspci -vvv把配置空间dump出来重点看BAR的地址和类型对不对。再用cat /proc/iomem看内存映射是否成功。两个信息对不上八成是硬件配置问题。在设备树Device Tree或ACPI里描述PCIE设备时地址空间属性要写对。我遇到过设备树里reg属性长度没对齐BAR大小导致映射长度截断后半段寄存器访问不到。做热插拔或动态重配置时记得配置空间是可能被重置的。驱动probe时要能容忍部分寄存器被恢复默认值关键配置要在适当时机重新写入。最后留个心眼有些低功耗状态会关闭部分地址空间唤醒后需要重新使能。电源管理代码里记得处理这个场景不然睡醒后设备“失忆”了。PCIE地址空间就像城市的道路规划内存空间是高速公路IO空间是老城区单行道配置空间是交通控制中心。把路标搞对了数据包才能高效到达。下次遇到PCIE设备访问异常先查这三张“地图”大概率能少熬几个夜。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2553295.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!