一、前言
之前看文章,看的云里雾里,梳理pcie的知识体系。
二、overview
pcie发展史:
pcie 2.0 - 3.0的编码方式进行了改变。
PCIe采用了端到端的全双工的传输设计,基于数据包的传输,设备之间通过link相连,link支持1到32个lane:
PCIE采用总线拓扑结构:
RC(Root Complex):RC是PCIE总线拓扑结构中的根节点,通常指的是主板上的PCIE控制器。RC是PCIE总线的起点,负责初始化和管理PCIE总线,并通过配置空间(Configuration Space)进行设备的寻址和初始化。
EP(Endpoint):EP是指连接到PCIE总线的终端设备,如显卡、网卡、存储控制器等。这些设备是PCIE总线的终点,通过PCIE总线与RC进行通信。
RP(Root Port):RP是主板上的PCIE插槽或端口,用于连接RC和EP之间的桥梁。RP在PCIE总线拓扑中扮演桥接角色,将RC与连接在其上的EP进行通信。
Switch:PCIE Switch是一种特殊的RP,它具有多个PCIE端口,用于连接多个EP。PCIE Switch允许多个设备同时通过PCIE总线与RC通信,扩展了PCIE总线的连接能力。
三、重要概念
1 配置空间
每个PCIe设备都有自己的独立的一段配置空间,PCI时期配置空间大小是256B, PCIe向下兼容,配置空间大小为4KB,前256B和PCI一致,后面的为PCIe拓展空间。
前256B一般称为PCI配置空间,后面的256~4K一般称为PCIe配置空间。
PCI空间存放了设备的基本信息,根据设备类型分为两种:
Type0: 设备空间,EP属于此类型0;
Type1: Bridge空间,RC的root port以及switch中的bridge属于此类型;
type1
Vendor ID(厂商ID):16位,用于标识PCIE设备的制造商。由PCI-SIG(PCI Special Interest Group)分配给厂商;枚举设备时通常判断此VID来判断设备是否存在。
Device ID(设备ID):16位,用于标识特定厂商的不同PCIE设备型号。
Command Register(命令寄存器):16位,用于启用或禁用PCIE设备的各种功能。其中的一些标志位包括:
I/O Space Enable(I/O空间使能):启用设备的I/O地址空间。
Memory Space Enable(内存空间使能):启用设备的内存地址空间。
Bus Master Enable(总线主控制使能):允许设备成为PCIE总线的主控设备。
Memory Write and Invalidate(内存写入和失效):允许设备进行内存写入和失效操作。
Status Register(状态寄存器):16位,用于显示设备的当前状态,例如是否支持66MHz时钟、是否支持66MHz数据传输等。
Revision ID(版本ID):8位,用于标识设备的硬件版本号。
Class Code(类别代码):24位,用于标识设备的类别和功能。例如,指示设备是网络控制器、显卡还是存储控制器等。
Subclass Code(子类别代码):8位,更详细地描述设备的类别。
Prog IF(接口描述符):8位,用于标识设备的接口类型,以及特定接口的功能。
BIST (Built-In Self Test):8位,包含一些用于自检的标志位。
BARs(Base Address Registers):PCIE设备可以使用这些32位或64位的寄存器来指定设备的I/O地址空间和内存地址空间的基地址。
Subsystem Vendor ID(子系统厂商ID):16位,用于标识连接到PCIE设备上的子系统(通常是主板)的制造商。
Subsystem ID(子系统ID):16位,用于标识连接到PCIE设备上的子系统的型号。
Expansion ROM Base Address:32位,用于指定扩展的只读存储器(Expansion ROM)的基地址。
Capabilities Pointer:8位,指向PCIE设备的扩展能力列表。
Interrupt Line和Interrupt Pin:用于配置设备的中断信息,包括中断线路和中断引脚。
Subordinate Bus Number(下级总线号):8位,用于指定连接到当前PCIE设备的下一级PCIE总线的总线号。当一个PCIE设备上有其他PCIE设备连接时,Subordinate Bus Number指定了这些下级设备所使用的总线号范围。这有助于系统在启动时自动分配资源和配置多级PCIE总线结构
type2
Vendor ID(厂商ID):16 位,用于标识 PCIE 设备的制造商。由 PCI-SIG(PCI Special Interest Group)分配给厂商。
Device ID(设备ID):16 位,用于标识特定厂商的不同 PCIE 设备型号。
Command Register(命令寄存器):16 位,用于启用或禁用 PCIE 设备的各种功能。其中的一些标志位包括:
I/O Space Enable(I/O 空间使能):启用设备的 I/O 地址空间。
Memory Space Enable(内存空间使能):启用设备的内存地址空间。
Bus Master Enable(总线主控制使能):允许设备成为 PCIE 总线的主控设备。
Memory Write and Invalidate(内存写入和失效):允许设备进行内存写入和失效操作。
Status Register(状态寄存器):16 位,用于显示设备的当前状态,例如是否支持 66MHz 时钟、是否支持 66MHz 数据传输等。
Revision ID(版本ID):8 位,用于标识设备的硬件版本号。
Class Code(类别代码):24 位,用于标识设备的类别和功能。例如,指示设备是网络控制器、显卡还是存储控制器等。
Subclass Code(子类别代码):8 位,更详细地描述设备的类别。
Prog IF(接口描述符):8 位,用于标识设备的接口类型,以及特定接口的功能。
BIST(Built-In Self Test):8 位,包含一些用于自检的标志位。
BARs(Base Address Registers):PCIE 设备可以使用这些 32 位或 64 位的寄存器来指定设备的 I/O 地址空间和内存地址空间的基地址。
Subsystem Vendor ID(子系统厂商ID):16 位,用于标识连接到 PCIE 设备上的子系统(通常是主板)的制造商。
Subsystem ID(子系统ID):16 位,用于标识连接到 PCIE 设备上的子系统的型号。
Expansion ROM Base Address:32 位,用于指定扩展的只读存储器(Expansion ROM)的基地址。
Capabilities Pointer:8 位,指向 PCIE 设备的扩展能力列表。
Interrupt Line 和 Interrupt Pin:用于配置设备的中断信息,包括中断线路和中断引脚。
PCIe配置空间的布局非常灵活,主要是通过链表来串联多个Capability寄存器。在原有的配置空间中,有一个寄存器指定了第一个Capability的位置,而第一个Capability又会指向下一个Capability,从而构成了一个Capability链表。具体可参考以下示意图:
在PCIe设备的配置空间中,常见的Capability寄存器用于扩展设备的功能和特性。以下是一些比较常见的Capability寄存器:
PCI Express Capability(PCIE Capability):这是PCIe设备中最常见的Capability寄存器。它提供了PCIe设备的一些基本信息,如支持的PCIe规范版本、最大链接速度和宽度等。
MSI Capability(Message Signaled Interrupt Capability):这个Capability用于支持Message Signaled Interrupts(MSI),一种更高效的中断传输方式。
MSI-X Capability(Message Signaled Interrupts eXtended Capability):类似于MSI Capability,但支持更多的中断向量,提供了更高级的中断处理方式。
Vendor-Specific Capability(厂商特定Capability):不同厂商可以根据自己的需求定义自己的Capability来支持特定的功能和扩展。
Power Management Capability(电源管理Capability):用于支持设备的低功耗和电源管理功能。
Advanced Error Reporting Capability(高级错误报告Capability):提供了更丰富的错误报告和调试信息,有助于系统故障排查。
AER Endpoint Reporting Capability(AER端点报告Capability):在端点设备上支持高级错误报告,允许端点设备主动报告错误。
Virtual Channel Capability(虚拟通道Capability):支持虚拟通道,用于在PCIe链路上提供多个优先级通道以进行流量管理。
PCI-X Capability:支持PCI-X(PCI eXtended)标准,提供更高的总线速度和扩展性。
SR-IOV Capability(Single Root I/O Virtualization Capability):用于支持单根I/O虚拟化,允许物理设备虚拟化为多个虚拟设备。
需要注意的是,不同的PCIe设备可能支持不同的Capability寄存器,具体取决于设备的功能和实现。PCIe规范允许厂商定义自己的Capability来支持特定的扩展功能,因此可能会在不同设备上看到其他类型的Capability。
2 数据包
和网络OSI类似,有物理层,链路层,传输层。
PCIe的数据包组成以及各个字段和层的关系如下:
3 传输类型
配置读写(Configuration Read/Write):这种传输类型用于对PCIe设备的配置空间进行读取和写入操作。配置空间包含了设备的标识信息、寄存器和Capability寄存器等配置参数。
存储器读写(Memory Read/Write):存储器读写传输用于从一个PCIe设备的内存读取数据或将数据写入到PCIe设备的内存中。这种传输允许设备之间在内存地址空间中进行数据交换。
数据传输(Data Transfer):数据传输传输类型用于在设备之间传输数据。它可以是内存到内存的数据传输,也可以是设备到设备的数据传输。
消息传输(Message):消息传输用于在设备之间传递命令、通知或控制信息。这种传输类型用于在不需要进行数据传输的情况下,进行设备之间的通信。
IO读写(IO Read/Write):IO读写传输用于从IO地址空间进行读取和写入操作。这种传输类型允许设备使用I/O地址空间进行简单的输入输出操作。
原子操作(Atomic Operation):原子操作传输类型用于执行原子操作,确保在多个设备之间进行原子性的读-修改-写(read-modify-write)操作,以防止竞争条件。
这些传输类型是PCIe总线上数据传输和通信的基础,它们允许不同的PCIe设备之间在高速和可靠的总线上进行数据交换和通信。这些传输类型使得PCIe成为现代计算机系统中高性能和高可扩展性的总线解决方案。
4 数据包路由
在PCIe总线上的数据包主要有三种路由的方式:
基于PCI域地址:存储器读写使用此方式;
基于ID(BDF,B=bus id,D=device id,F=function id):配置读写,完成报文等;
隐式路由:主要用于messages的传输;
在PCIe(Peripheral Component Interconnect Express)总线上,数据包的路由是通过目标设备的设备ID(Device ID)和总线号(Bus Number)来实现的。PCIe总线采用一种分层结构的拓扑,其中每个PCIe设备都通过设备ID和总线号在总线上唯一标识自己。
数据包的路由方式如下:
源设备(例如,PCIe Root Complex或PCIe Switch)在发出数据包时,根据目标设备的设备ID和总线号确定数据包的目标。
数据包的目标设备ID可以是一个具体的设备,也可以是一个桥接设备(如PCIe到PCI桥或PCIe到PCIe桥)。桥接设备会将数据包传递给其上连接的目标设备或继续向上级桥进行传递。
当数据包到达目标设备后,设备ID与目标设备的设备ID匹配,设备将处理数据包或响应请求。
如果数据包的目标设备是一个桥接设备,则该桥接设备会将数据包传递给连接在其上的下级设备。桥接设备会在转发数据包时,根据数据包的设备ID和总线号来进行选择。
数据包可以在多级桥接设备之间进行传递,直到到达目标设备为止。
在PCIE总线上,每个设备都有一个唯一的设备ID和总线号。这些ID和总线号在配置空间中定义,并由系统固件(如BIOS或UEFI)配置和分配。通过使用设备ID和总线号,PCIE总线能够确定数据包的路径,从而将数据包有效地传输到其目标设备。
这种数据包的路由方式使得PCIE总线能够支持多级拓扑结构和灵活的设备连接,同时确保数据包按照正确的路径传递,从而实现高性能和高可靠性的数据传输。
5 PCIE域地址空间
在域pcie组成的系统中,有CPU地址空间,有pcie域地址空间;
cpu侧:
海思的core分可预期地址空间和非可预期地址空间,其中寄存器地址空间是非可预取,DDR的地址是可预取;
在arm coer中,pcie的地址空间是device属性,nocache,不存在cache一致性的问题;
Pcie测:
pcie的地址中间是独立域arm统一编址的地址的;
一般的映射方式:
我们一般把A cpu的一段寄存器地址空间(非可预期地址空间或可预取地址空间)0xAXXXXXXX - 0xBXXXXXXX;
映射到pcie的域地址空间0x1XXXXXXX - 0x2XXXXXXX;
再把这段地址0x1XXXXXXX - 0x2XXXXXXX映射到B cpu的0xCXXXXXXX - 0xDXXXXXXX;
(这里有图展示就很直观了,暂时不方便提供)
6 BAR
BAR是EP设备实现其他设备访问自身资源的窗口,J5 EP模式下支持3个可配置的BAR:
BAR2:64bit,最大支持32GB。
BAR4、BAR5:32bit,最大支持4GB。
BAR本质上是一种映射,在EP端通过配置ATU把本地的CPU域地址和BAR进行关联,这样PCI总线上对BAR的访问,会通过ATU转换为对EP CPU域的访问。
需要注意的是因为BAR是需要分配对应大小的PCI域地址空间的,所以需要检查RC是否有足够大的PCI域地址空间用于所有EP设备的BAR分配。
(在Marvell的代码在,他的概念是window)。
7 ATU
在PCIe(Peripheral Component Interconnect Express)中,ATU(Address Translation Unit)是用于地址转换的硬件单元。ATU主要用于处理PCIe设备之间的内存读写和I/O读写操作,将设备的物理地址转换为系统内存的地址或IO地址。地址转换单元,分为进和出两个方向:outbound&inbound,outbound为CPU域转换为PCI域地址,inbound反之。例如EP的BAR配置使用的是inbound,用于外部的设备使用PCI域地址访问EP DDR。
8 总线枚举
RC负责PCIe总线上所有设备的资源分配,RC在遍历总线上的设备过程中,除了对设备进行初始化,还需要对所有设备使用的资源进行统一的分配:EP
分配ID:基于深度遍历(DFS)为每个设备生成ID,对EP发起配置访问请求,EP在收到配置访问请求的过程中得到分配的ID,记录在EP的PCIe IP中,用于后续的通讯中报头的requester ID填充。
分配EP BAR的PCI域地址:从RC的PCI域地址中(上面提到的两段J5 PCI域地址)根据EP设备的BAR数量和大小进行分配,并把分配的地址写入EP的BAR寄存器中。
当RC遍历总线完成后,所有的EP ID以及其BAR都被分配好并配置,RC与EP,EP与EP之间可以通过分配好的地址进行数据通讯。
9 Switch
RC和upstream port连接,EP和downstream port连接。
内部由多个桥组成,每个桥都有自己的配置空间,RC在枚举PCIe总线过程中,会对每个桥进行配置,其中最为重要的是base和limit寄存器,表示桥下所有设备的起始PCI域地址和长度:
10 P2P
p2p,即为peer-to-peer,是指EP之间不通过RC,直接进行数据通讯。
虽然数据不经过RC,但是并不意味着RC可以省略,因为EP BAR的PCI域地址,是由RC分配的,EP设备的初始化也是由RC进行的。
当EP被RC正确的初始化并分配好PCI总线地址,EP之间就可以使用BAR PCI域地址进行直接的数据访问。
11中断
PCIe的中断只有一个方向:EP发送,RC接收。
INTx:PCI的遗留产物,已经被MSI/MSI-X取代,无法和MSI/MSI-X同时启用。
MSI:基于消息的中断,这里的消息非上面提到的"messages“传输类型,最多支持32个中断,J5 EP和RC模式下都支持。
MSI-X:MSI的进阶版本,支持更多的中断数(受限于软件分配的大小),J5 EP模式下支持,RC模式下不支持。
MSI/MSI-X本质是写一个数据到RC端的DDR地址,RC会监控这个地址,检测到有数据写入就会触发本地的MSI中断,最终调用到注册的中断响应函数。
12 DMA
PCIe(Peripheral Component Interconnect Express)中的DMA(Direct Memory Access)是一种数据传输技术,允许PCIe设备直接访问系统内存,而无需通过CPU的干预。DMA可以实现高效的数据传输,从而提高数据传输速率和降低CPU负载;