linux之PCIE 的ECAM 机制和初始化

一、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为例子)

  1. 假设 ECAM 基址被设置为 0x80000000。系统可以通过如下方式计算每个设备的 ECAM 地址:
    1. 对于总线 0 上的设备(Root Ports):每个 Port 是 Type 1 PCI-PCI 桥,拥有独立配置空间 
      1. RP1 的 ECAM 地址为:0x80000000 + (0 << 20) + (0 << 15) + (0 << 12),即 0x80000000。
      2. RP2 的 ECAM 地址为:0x80000000 + (0 << 20) + (1 << 15) + (0 << 12),即 0x80008000。
    2. 对于 RP1 下的 Endpoint(EP1):
      1. EP1 被分配在总线 1,其 ECAM 地址为:0x80000000 + (1 << 20) + (0 << 15) + (0 << 12),即 0x80100000。
    3. 对于 RP2 下的 Endpoint(EP2):
      1. EP2 被分配在总线 2,其 ECAM 地址为:0x80000000 + (2 << 20) + (0 << 15) + (0 << 12),即 0x80200000。

操作系统可以通过计算出的 ECAM 地址 0x80100000 来访问总线 1 上 EP1 的配置空间,并读取其 Vendor IDDevice 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值