一、ECAM 和CAM 的机制是什么作用
1.1 pcie 配置空间

PCI协议定义了256 byte配置空间供PCI设备使用,随着科技发展,PCI设备种类增多,各厂商自定义的cap已经不满足于256 byte空间,此外,并行总线的PCI设备传输速率已经达到了瓶颈,因此推出了PCIe设备以替代传统PCI设备。
PCIe设备将配置空间扩展到了4096 byte,且前256 byte兼容PCI配置空间,因此,PCIe设备可以很好的替代PCI设备,在主机主板支持的情况下,它们能在同一系统下工作。如上图所示,传统PCI设备和PCIe设备都拥有标准配置空间头(0-0x3f),但传统PCI设备的其他cap只能放置于 0x3f~0xff 之间的配置空间中,而PCIe设备的其他cap,则可以放置于 0x3f~0xfff 之间的配置空间中,这意味着PCIe设备能提供更强劲的功能。
1.2 如何访问pcie 配置空间
PCI Express配置模型支持两种配置空间访问机制:
- PCI-compatible Configuration Access Mechanism(CAM,PCI兼容配置访问机制,参见协议第7.2.1节)
- PCI Express Enhanced Configuration Access Mechanism(ECAM,PCI Express增强型配置访问机制,参见协议第7.2.2节)
CAM 模式是PCI协议定义的访问方式,而ECAM则是PCIe协议定义的访问方式。为了兼容传统PCI设备,PCIe协议要求ECMA机制与CAM机制访问配置空间前256 byte等效。
1.3 CAM
以x86 为例,
X86处理器定义了两个I/O端口寄存器,分别为CONFIG_ADDRESS何CONFIG_DATA寄存器,器地址为0xCF8和0xCFC,CAM访问机制就是通过这两个寄存器实现的。简单来说就是把需要访问的PCI设备信息按特定格式写入CONFIG_ADDRESS(0xCF8)寄存器,然后读写CONFIG_DATA(0xCFC)寄存器即可。
CONFIG_ADDRESS寄存器信息格式如下。

- Enable位,第31位。该位为1时,对CONFIG_DATA寄存器进行读写时将引发PCI总线的配置周期。
- Bus Number字段,第23~16位,访问的PCI设备总线号,每个pci桥扩展出来的信号总线编号,最多256个总线号,host主桥出来的是0号。
- Device Number字段,第15~11位,访问的PCI设备设备号,每个总线编号下的设备编号,最多32个设备号,从0开始。
- Function Number字段,第10~8位,访问的PCI设备功能号,设备内部实现的功能编号,最多8个,从0开始。
- Register Number字段,第7~2位,访问的的配置空间寄存器号,由于寄存器是DW访问了,所以不需要第1~0位。
将PCI设备的总线号、设备号、功能号以及寄存器号填写到CONFIG_ADDRESS寄存器并使能第31位,然后读写CONFIG_DATA寄存器即可读写指定PCI设备的指定寄存器了。可以注意到,Register Number字段只有8bit(DW访问),所以只能访问到配置空间的前256byte。
1.4 ECAM
ECAM(Enhanced Configuration Access Mechanism)利用一个扁平的存储器映射地址空间来访问PCIe设备的配置寄存器。根据特定的格式组装访问存储器空间地址,就可以确定访问PCIe设备的配置寄存器,并且将数据更新(对于写操作)或返回(对于读操作)被寻址寄存器的内容。从存储器地址空间到PCI Express配置空间地址的映射格式参见下图定义。

相比CAM机制,其增加了11~8 bit,用于扩展访问256byte~4k之间的配置空间寄存器。Bus Number正常应该为20~27bit,正好对应256个bus号。更高的31~28 bit则用来作为ECAM的base地址,比如:
X86架构
[root@localhost ~]# cat /proc/iomem | grep MMCONFIG
c0000000-cfffffff : PCI MMCONFIG 0000 [bus 00-ff][root@localhost ~]# cat /proc/iomem | grep MMCONFIG
f8000000 - fbffffff : PCI MMCONFIG 0000 [bus 00-3f]//可以看到base地址既有0xf8000000,也有0xc0000000
ARM架构
[root@localhost ~]# cat /proc/iomem | grep ECAM
40000000-4fffffff : PCI ECAM//可以看到base地址为0x40000000
那linux系统怎么知道ECAM机制的base地址呢?对于有BIOS的系统,则由BIOS告诉linux内核;对于ARM(不带BIOS)的系统,则由设备树中填写。
ECAM机制是如何实现的呢?很简单,就是CPU发出地址访问请求,由地址转换部件判断地址是否为预留的ECAM地址区间,再将请求路由给RC或host主桥,当RC或host主桥接收到这段地址的访问,按上述格式解析填写CFG TLP报文下发即可。注意:地址转换部件不是一个真正存在的实体,更多是指功能概念。

1.5 ECAM 地址分配
为不同设备分配 ECAM 地址:(假设rc有2个rp,每个rp下挂1个ep为例子)
- 假设 ECAM 基址被设置为 0x80000000。系统可以通过如下方式计算每个设备的 ECAM 地址:
- 对于总线 0 上的设备(Root Ports):每个 Port 是 Type 1 PCI-PCI 桥,拥有独立配置空间
- RP1 的 ECAM 地址为:0x80000000 + (0 << 20) + (0 << 15) + (0 << 12),即 0x80000000。
- RP2 的 ECAM 地址为:0x80000000 + (0 << 20) + (1 << 15) + (0 << 12),即 0x80008000。
- 对于 RP1 下的 Endpoint(EP1):
- EP1 被分配在总线 1,其 ECAM 地址为:0x80000000 + (1 << 20) + (0 << 15) + (0 << 12),即 0x80100000。
- 对于 RP2 下的 Endpoint(EP2):
- EP2 被分配在总线 2,其 ECAM 地址为:0x80000000 + (2 << 20) + (0 << 15) + (0 << 12),即 0x80200000。
- 对于总线 0 上的设备(Root Ports):每个 Port 是 Type 1 PCI-PCI 桥,拥有独立配置空间
操作系统可以通过计算出的 ECAM 地址 0x80100000 来访问总线 1 上 EP1 的配置空间,并读取其 Vendor ID、Device ID 以及其他信息。
枚举过程从设备号 0 开始,逐个扫描设备号,直到遇到一个没有设备存在的设备号为止,从而得知总线 0 上挂载的设备数量。在你的例子中,系统扫描到设备号 2 时没有设备存在,因此得知总线 0 上只有 2 个 Root Port。
在内核中, 有定义ECAM 地址宏:
#define PCI_ECAM_ADDRESS(Bus,Device,Function,Offset) \
(((Offset) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20))
1.6 用户态访问配置空间工具
1.6.1 lspci
通过lcpsi可以查看系统下有哪些PCIe设备。
[root@localhost ~]# lspci
00:00.0 Host bridge: Intel Corporation Device 4648 (rev 02)
00:02.0 VGA compatible controller: Intel Corporation AlderLake-S GT1 (rev 0c)
00:0a.0 Signal processing controller: Intel Corporation Device 467d (rev 01)
00:0e.0 RAID bus controller: Intel Corporation Volume Management Device NVMe RAID Controller
00:14.0 USB controller: Intel Corporation Device 7ae0 (rev 11)
00:14.2 RAM memory: Intel Corporation Device 7aa7 (rev 11)
00:15.0 Serial bus controller [0c80]: Intel Corporation Device 7acc (rev 11)
00:15.1 Serial bus controller [0c80]: Intel Corporation Device 7acd (rev 11)
00:15.2 Serial bus controller [0c80]: Intel Corporation Device 7ace (rev 11)
00:16.0 Communication controller: Intel Corporation Device 7ae8 (rev 11)
00:17.0 SATA controller: Intel Corporation Device 7ae2 (rev 11)
00:1a.0 PCI bridge: Intel Corporation Device 7ac8 (rev 11)
00:1b.0 PCI bridge: Intel Corporation Device 7ac0 (rev 11)
00:1b.4 PCI bridge

251

被折叠的 条评论
为什么被折叠?



