一、PCIe概述
1、PCIe速度
- PCI采用总线共享式通讯方式;PCIe采用点到点(
Endpoint to Endpoint
)通讯方式,互为接收端和发送端,全双工,基于数据包传输; - 两个PCIe设备之间的连接称作一条链路(
link
), 一条链路可以包含多个通道(每对接收和发送对称作一个通道(lane
)),可增加通道个数来满足更高的带宽要求。
物理底层采用差分信号(PCI链路采用并行总线,而PCIe链路采用串行总线),一条Lane中有两组差分信号,共四根信号线,而PCIe Link可以由多条Lane组成,可以支持1、2、4、8、12、16、32条;
版本 | 编码方案 | 传输速率 | X1 吞吐量 | X4 吞吐量 | X8 吞吐量 | X16 吞吐量 |
1.0 | 8b/10b | 2.5GT/s | 250MB/s | 1GB/s | 2GB/s | 4GB/s |
2.0 | 8b/10b | 5GT/s | 500MB/s | 2GB/s | 4GB/s | 8GB/s |
3.0 | 128b/130b | 8GT/s | 984.6MB/s | 3.938GB/s | 7.877GB/s | 15.754GB/s |
4.0 | 128b/130b | 16GT/s | 1.969GB/s | 7.877GB/s | 15.754GB/s | 31.508GB/s |
5.0 | 128b/130b | 32 or 25GT/s | 3.9 or 3.08GB/s | 15.8 or 12.3GB/s | 31.5 or 24.6GB/s | 63.0 or 49.2GB/s |
PCIe吞吐量计算方法: 吞吐量 = 传输速率 * 编码方案
- PCIe1.0传输速率为2.5Gb/s,物理层使用8/10编码(8Bit数据在物理线路上需要10比特传输),PCIe1.0 x 1的带宽 =
2.5Gb/s
*8/10bit
=2Gb/s
=2000Mb/s
=250MB/s
- PCIe2.0传输速率为5Gb/s,物理层使用8/10编码, PCIe2.0 x 1的带宽 =
5Gb/s
*
8/10bit
=4Gb/s
=4000Mb/s
=500MB/s
- PCIe3.0传输速率为8Gb/s,物理层使用128/130编码进行数据传输,PCIe3.0 x 1的带宽 =
8Gb/s
*128/130bit
≈7.8769Gb/s
=7876.9Mb/s
=984.6MB/s
Mb/s
: 兆比特每秒,指每秒传输的比特位数
MB/s
: 兆字节每秒,指每秒传输的字节数量,1MB/s
=8Mb/s
2、PCIe拓扑结构
PCIe采用树形拓扑结构, 由root complex
,switch
,endpoint
等类型的PCIe设备组成
root complex(RC)
: 根桥设备,CPU和PCIe拓扑之间的接口,负责PCIe报文的解析和生成。RC会将CPU的request
转换成PCIe的4种不同的请求(Configuration
、Memory
、I/O
、Message
);switch
: PCIe的转接器设备(扩展PCIe端口),为挂在它上的设备(endpoint
或switch
)提供路由和转发服务。PCIe endponit(EP)
: PCIe终端设备,如网卡、显卡等。PCI Express-PCI bridge
: 桥接设备,连接其他的PCI总线、PCI-X、PCIe总线。
和PCI并行总线不同,PCIe的总线采用了高速差分总线,并采用端到端的连接方式, 因此在每一条PCIe链路中两端只能各连接一个设备, 如果需要挂载更多的PCIe设备,那就需要用到switch
转接器。
Switch
扩展了PCIe端口,靠近RC的那个端口,我们叫上游端口(upstream port
),而分出来的其他端口,我们叫下游端口(downstream port
)。一个Switch只有一个上游端口,可以扩展出若干个下游端口。下游端口可以直接连接Endpoint
,也可以连接 Switch
,扩展出更多的PCIe端口。
3、PCIe信号定义
- PETpx、PETnx: 数据发送器差分线对;
- PERpx、PERnx: 数据接收器差分线对,x代表通道号;
- PERST#: 全局复位信号有效时(#:低电平有效),PCIe设备将对内部逻辑进行复位操作;
- REFCLK+、REFCLK-: PCIe参考时钟信号;
- WAKE#: CPU向PCIe设备提供唤醒请求后,为该PCIe设备提供主电源Vcc;
SMCLK: 系统管理总线时钟;SMDAT: 系统管理总线数据;
4、PCIe分层结构
-
Transaction Layer:【事务层】负责
TLP
包(Transaction Layer Packet
)的封装与解封装,此外还负责QoS,流控、排序等功能; -
Data Link Layer:【数据链路层】负责
DLLP
包(Data Link Layer Packet
)的封装与解封装,此外还负责链接错误检测和校正,使用Ack/Nak协议来确保传输可靠; -
Physical Layer:【物理层】 处理所有的
Packet
数据物理传输,发送端数据分发到各个Lane
传输(stripe
),接收端把各个Lane
上的数据汇总起来(De-stripe
),每个Lane
上加扰(Scramble
,让0和1分布均匀,去除信道的电磁干扰EMI)、去扰(De-scramble
),以及8/10或者128/130编码解码等。
PCIe传输的数据从上到下,都是以packet的形式传输的,每个packet都是有其固定的格式的。
-
红色部分【事物层】:
Header
和Data
是事务层上层给的信息,事务层给它末尾加ECRC
(End-to-End CRC
, 端到端CRC
)字段,,就构成了一个TLP
(Transaction Layer Packet
); -
蓝色部分【数据链路层】: 负责在
TLP
中添加一个序列号、LCRC
字段(Link CRC
, 链路CRC
),构成了一个DLLP
包(Data Link Layer Packet
); -
绿色部分【物理层】:
DLLP
下传到物理层,头上加个Start
,末尾加个End
符号,把这些数据分派到各个Lane
上,然后每个Lane
上加扰码,经8/10或128/130编码,最后通过物理传输介质传输给接收方。( 解析是一个逆向的过程)
二、PCIe事物层
事务层根据上层(软件层或者应用层)请求(Request
)的类型、目的地址和其它相关属性,把这些请求打包,产生TLP
(Transaction Layer Packet
)。
TLP
=Request TLP
【请求】 +Completion TLP
【响应】
1、TLP请求
根据软件层的不同请求,事务层产生四种不同的TLP请求:
-
Memory: 【内存空间访问】,数据在彼此的
Memory
之间交互, PCIe总线上的主流传输;针对32bit
寻址,支持4G
的地址空间,针对64bit
寻址,支持16G
的地址空间; -
IO:【 IO空间访问】,新的PCIe设备设备的物理空间只支持内存映射(
Memory map
)到Host主存,存在访问IO空间的TLP,是为了兼顾老设备;PCI最大支持4G
的IO空间,但受限于x86处理器
的IO空间
(16bits
带宽),很多平台将PCI的IO地址空间限定在64KB
; -
Configuration:【配置空间访问】,由Host发起(确切的说是RC),往往只在上电枚举和配置阶段会发起
Configuration
的访问; 备注:x86 CPU
可以直接访问memory
空间和I/O
空间,配置空间则不能直接访问,而是通过IO映射
的数据端口
和地址端口间接访问
PCI的配置空间; -
Message: PCI通过边带信号线(
sideband signal
)传输中断、错误以及电源管理相关信息,而PCIe是通过Packet
传输,只有在中断、错误等情况下,才会有Message TLP
。
补充:
x86 CPU
采用 独立编址的方式,将memory
操作与IO
操作分开了,才有了memory空间
和IO空间
的区分;ARM
、Power PC
处理器把寄存器与内存 统一编址,访问寄存器就通过访问一般的内存指令进行,这类CPU没有专门用于设备l/O的指令。
2、TLP响应
-
Non-Posted TLP: 要求设备必须响应,对方通过返回一个
Completion TLP
来作为响应(可包含需要返回的有效数据或状态),如Configuration
、IO
、Memory Read
; -
Posted TLP: 不要求对端设备响应(
Posted
:邮政)。投递消息后不保证接收方一定能收到,存在丢数据的风险(概率很小),因此数据链路层提供了ACK/NAK
机制,一定程度上能保证TLP正确交互;只有Message
、Memory Write
采用Posted TLP
方式。
TLP事务种类 | 名称缩写 |
---|---|
Memory Read | MRd |
Memory Write | MWr |
Configuration Read(Type 0 and Type 1) | CfgRd0, CfgRd1 |
Configuration Write(Type 0 and Type 1) | CfgWr0,CfgWr1 |
Message Request with Data | MsgD |
Message Request without Data | Msg |
Completion with Data(响应包中含数据) | CplD |
Completion without Data(响应包中不含数据) | Cpl |
例1: Endpoint
想读Host
内存的数据,因此,它在事务层上生成一个Memory Read TLP
,该MRd
一路向上,翻过B,越过A,最终到达Root Complex
。RC
收到该Request
,就到内存中取该Endpoint
所需的数据,RC
通过Completion with Data TLP
(CplD
)返回数据,原路返回到EP
。
一个TLP
,最多只能携带4KB
有效数据,如果EP
需要读16KB
的数据,RC
必须返回4个CplD
给Endpoint
(EP只需发1个MRd
)。
例2: Host
想往某个EP
写入数据,因此RC
在其事务层生成一个Memory Write TLP
(要写的数据在该TLP中),翻过A,越过B,直到目的地。Memory Write TLP
是Posted
的,因此,EP
收到数据后不需返回Completion TLP
。
由于一个TLP只能携带4KB数据,Host想往Endpoint
上写入16KB
数据,RC
必须发送4个MWr TLP
。
3、TLP结构
- Header: 根据上层请求内容生成
TLP Header
(发送者的相关信息、目标地址、TLP类型、数据长度等); - Data Payload: 有效载荷数据。该域不是必须的(不是每个TLP都必须携带数据,如存储器读操作、配置和IO写完成操作,数据是由目标设备通过
Completion TLP
返回),最大数据长度为1024DW(4K)
; - ECRC(End to End CRC): 根据
Header
和Data
生成CRC,在接收端根据收到的TLP,重新生成Header
和Data
的CRC,和收到的CRC比较,相等说明数据在传输过程中没有出错,否则就有错(可以设置不加CRC);
一个Header大小可以是3DW
(DW:双字,一个DW为4Byte),也可以是4DW
(16Byte),格式和内容随事务类型变化,总结如下:
Completion TLP(响应TLP)
的Header大小总是3DW
;-
Configuration
的Header大小总是3DW
; Message TLP
的Header 大小总是4DW
;- 如果Host内存空间小于4GB,则
Memory
读写TLP Header
大小为3DW
,大于4GB则为4DW
。
以4DW
的TLP Header
为例:
- Fmt[2:0]: Format,表明该TLP是否带有数据,Header是
3DW
还是4DW
;所有的读操作(存储、IO、配置)TLP都不带数据,而写请求(存储、IO、配置)的TLP带数据,其他TLP可能带、也可能不带数据。
Fmt[2:0] | 描述 |
000 | 3 DW header,无数据 |
001 | 4 DW header,无数据 |
010 | 3 DW header,有数据 |
011 | 4 DW header,有数据 |
100 | TLP Prefix(可选功能) |
- Type[4:0]: TLP类型,与
Fmt
字段一起用于规定事务类型、帧头长度和是否有数据负载。如果存储器读写 TLP 支持 64 位地址模式时,TLP 头长度为 4DW,否则为 3DW。而完成报文的 TLP 头不含有地址信息,使用的 TLP 头长度为 3DW,其中 Byte4~Byte15 格式与 TLP 类型有关。
PCIe 总线规范还规定了 MRdLk 报文(锁定存储器读请求),该报文的作用是与 PCI 总线的所操作相兼容,但是 PCIe 总线规范不建议用户使用该功能,因为这将极大地影响 PCIe 总线的数据传送效率。
PCIe 总线规范使用 Fmt 字段区分读写操作,当 Fmt 是“带数据”的报文一定是“写操作”;当 Fmt 字段是不带数据的报文,一定是“读操作”。
TLP | Fmt[1:0] | Type[4:0] |
Memory Read Request(MRd):存储器读请求 | 00 = 3 DW header,无数据 01 = 4 DW header,无数据 | 0 0000 |
Memory Read Lock Request(MRdLk):锁定存储器读请求 | 00 = 3 DW header,无数据 01 = 4 DW header,无数据 | 0 0001 |
Memory Write Request(MWr):存储器写请求 | 10 = 3 DW header,有数据 11 = 4 DW header,有数据 | 0 0000 |
IO Read Request(IORd):IO读请求 | 00 = 3 DW header,无数据 | 0 0010 |
IO Write Request(IOWr):IO写请求 | 10 = 3 DW header,有数据 | 0 0010 |
Config Type 0 Read Request( CfgRd0):Type0配置读请求 | 00 = 3 DW header,无数据 | 0 0100 |
Config Type 0 Write Request( CfgWr0):Type0配置写请求 | 10 = 3 DW header,有数据 | 0 0100 |
Config Type 1 Read Request( CfgRd1):Type1配置读请求 | 00 = 3 DW header,无数据 | 0 0101 |
Config Type 1 Write Request( CfgWr1):Type1配置写请求 | 10 = 3 DW header,有数据 | 0 0101 |
Message Request(Msg):消息请求 | 01 = 4 DW header,无数据 | 1 0r[2:0] |
Message Request with Data(MsgD):带数据的消息请求 | 11 = 4 DW header,有数据 | 1 0r[2:0] |
Completion( Cpl):完成 | 00 = 3 DW header,无数据 | 0 1010 |
Completion with Data(CplD):带数据的完成 | 10 = 3 DW header,有数据 | 0 1010 |
Completion-Locked(CplLk):锁定完成 | 00 = 3 DW header,无数据 | 0 1011 |
Completion-Locked with Data(CplDLk):带数据的锁定完成 | 10 = 3 DW header,有数据 | 0 1011 |
-
R: 保留字段(
reserve
),应被置为0; -
TC[2:0] : 表示当前传输的等级(
Traffic Class
),有 8 种传输类型(TC0~TC7,默认为 0),该字段为 PCIe 的 QoS(Quality of Service
)相关。目前多数处理器系统的 RC 仅支持一个 VC 通路(Virtual Channel,虚拟通道,VC0~VC7
),多数 EP 中只含有一个 VC,因此这些 EP 在发送 TLP 时仅用 TC0。不同的 TC 使用 PCIe 链路中不同的 VC,而不同的 VC 仲裁机制不同,EP 或者 RC 可以通过调整 TLP 中的 TC 字段,从而调整 TLP 的优先级。 -
Attr[2:0]: 属性(
Attrbiute
),Attr[2]
:表示该 TLP 是否支持 PCIe 总线中的ID-based Ordering
;Attr[1]
:表示是否支持Relaxed Ordering
;Attr[0]
:表示该 TLP 在经过 RC 到达存储器时,是否需要进行 Cache 一致性处理。
Attr[2] | Attr[1] | 类型 |
0 | 0 | 缺省,即强序模型 |
0 | 1 | PCI-X Relaxed Ordering模型 |
1 | 0 | ID-based Ordering(IDO)模型 |
1 | 1 | 同时支持Relaxed Ordering和IDO模型 |
-
TH: 表示
TLP
中是否含有TLP处理信息提示(TLP Processing Hints
),TLP 发送端可以使用 TPH 信息,通知接收端即将访问数据的特性,以便接收端合理地预读和管理数据。 -
TD:
TLP Digest
,该bit置位,说明该TLP包含ECRC,接收端应该做CRC校验; -
EP:
Poisoned Data
, 表示当前 TLP 中的Data Payload
是否有效(1:有效、0:无效); -
AT[1:0]: 地址种类(
Address Type
),在一些 PCIe 设备中设置了 ATC(Address Translation Cache
)部件,该部件的主要功能是进行地址转换,只有在支持IOMMU
技术的处理器系统中,PCIe 设备才能使用该字段。该字段的主要目的是为了方便多个虚拟主机共享同一个 PCIe 设备。 -
Length[9:0]: 该字段用来描述
Data Payload
数据有效负载的大小(单位:DW),TLP最大数据长度4KB(10bit、最大1024,单位DW
);例如存储器读请求时,TLP 中没有 Data Payload 字段,此时使用 Length 字段表示需要读取n个DW( 0≤n≤1024);该长度总是DW的整数倍,如果TLP的数据不是DW(4Byte
)的整数倍,则需要用到下面两个域:Last DW BE
和1st DW BE
。 -
DW BE: PCIe 总线以字节为基本单位进行数据传递,但是 length 字段以 DW 为最小单位。为此 TLP 使用
Last DW BE
和First DW BE
两个字段进行字节使能,使得在一个 TLP 中,有效数据负载以字节为单位。
4、TLP Memory
PCIe设备开放给Host访问的设备空间,首先会映射到Host的内存空间,Host如果想访问设备的某个空间,TLP Header
中的地址应设置为该访问空间在Host内存的映射地址。
Memory
读写请求使用地址路由
方式进行数据传递。- 如果Host内存空间小于4GB,则
Memory
读写TLP Header
大小为3DW
,大于4GB则为4DW
。
因为对4GB内存空间,32bit
的地址用1个DW(Byte8-11
)就可以表示;而4GB以上的内存空间,需要2个DW(Byte8-15
)表示地址;
该TLP
经过Switch
时,Switch
会根据地址信息,把该TLP
转发到目标设备。之所以能唯一的找到目标设备,那是因为不同的Endpoint
设备空间会映射到Host
内存空间的不同位置。
每个设备在PCIe系统中都有唯一的ID,该ID由总线(Bus
)、设备(Device
)、功能(Function
)三者唯一确定,详见下一章。
- Request ID: 该字段包含生成TLP报文的
Bus Number[7:0]
、Device Number[4:0]
、Function Number[2:0]
,因为存储器写请求并不需要返回完成报文(Request ID
),但是仍予以保留。
Request ID
字段和Tag
字段合称为Transaction ID
,其作用是使接收端分析报文的Transaction ID
,确认报文到达的最终目的地。在同一段时间内,在当前的PCIe总线域中不能存在两个及以上的Transaction ID
相同存储器读请求。
- Tag: 该字段决定发送能暂存多少个同类型的TLP;假若Tag字段为5时,发送端能够暂存32个同类型的报文。
5、TLP Message
-
Message TLP
支持地址路由
和ID路由
,但绝大多数情况下使用隐式路由
方式进行数据传递。 -
Message TLP
用以传输中断、错误、电源管理等信息,取代PCI时代的边带信号传输。 -
Message TLP
的Header 大小总是4DW。
Message Code
来指定该Message
的类型,不同的Message Code
,最后两个DW的意义也不同。具体如下:
6、TLP路由方式
TLP的路由方式指TLP经过Switch
或者PCIe桥片
时采用哪条路径到达EP或RC的方法。PCIe总线继承了PCI总线的地址路由
和ID路由
方式,并新增了隐式路由
方式。
-
存储器和IO读写操作请求TLP使用基于地址的路由方式,这种方式使用TLP中的Address字段进行路由选径,最终到达目的地。
-
配置读写报文、
Vendor_Defined Messages
报文、cpl/cplD
报文使用基于ID路由方式,这种方式使用PCIe Bus Number
进行路由路径选择,在Switch
或多端口RC的虚拟PCI-to-PCI
桥配置空间中,包含如何使用PCI总线号进行路由路径选择的信息。 -
隐式路由是指从下游端口到上游端口进行数据传递的使用路由方式,或者用于RC向EP发出广播报文。隐式路由主要用于
Message
报文的传递,在PCIe总线中定义了一系列消息报文,包括INTx Interrupt Signaling
(中断信号)、Power Management Message
(电源管理信息)、Error Signal Message
(错误信息)等报文,在这些报文中,除了Vendor_Defined Messages
报文,其他所有信息报文都使用隐式路由方式。
三、PCIe配置空间
Configuration
的Header大小总是3DW。Configuration
读写请求使用ID路由
方式进行数据传递。BDF
(Bus-总线号
+Device-设备号
+Function-功能号
)构成了每个PCIe设备节点的身份证号,决定了唯一的目标设备;寻址基本单元是function
。Ext Reg Number(扩展寄存器号)
+Register Numbe(寄存器号)
相当于配置空间的偏移。
一个PCIe系统最多有256条Bus
,每条Bus上最多挂32个Device
,每个Device最多又能实现8个Function
,每个Function对应着4KB
的配置空间(PCI或者PCI-X为256Byte)。
Host软件可以读取该设备的配置空间来获取信息,也可以通过它来配置该设备。上电时,这些配置空间都需映射到Host的内存空间,因此,Host需要占用内存空间是:256*32*8*4KB =256MB
。
PCIe设备的配置空间是协议规定好的,Pcie的配置空间如下:
1、PCI标准配置空间头
PCI标准配置空间分 type0
(Endpoint)和 type1
(Switch)两种。
- Device ID: 设备
ID
, 表示该PCI
设备的设备号,只读。 - Vendor ID: 厂商
ID
, 表示生产该设备的厂商的编号(Intel ID
为8086
),只读。 - Status: 设备状态寄存器,用于保存
PCIe
设备的状态,如中断状态或运行产生错误时的状态。
Bit位 | 说明 |
bit[2:0] | 保留 |
bit3 | 中断状况:表示该功能有一个未完成的中断请求,默认值为0,仅与INTx消息有关 |
bit4 | 功能列表:表示在功能的PCI兼容配置空间前48个双字中存在一个或多个扩展功能寄存器组。PCIe功能都要求实现PCie功能结构,所以该比特必须设置为1 |
bit5 | 在PCI中支持66MHz,在PCIE中保留(为0)。 |
bit6 | UDF支持,现在保留 |
bit7 | 在PCI中支持快速背靠背,在PCIE中保留(为0)。 |
bit8 | 主控器数据奇偶错误,如果在命令寄存器设置了奇偶错误允许比特,且满足如下条件之一,请求者就设置主控器数据奇偶错误比特:①、如果请求者收到一个有错误的完成;②、如果请求者写请求中毒。如果清除了奇偶错误比特,则不会设置主控器数据奇偶错误比特。默认值为0 |
bit[10:9] | PCI中的DEVSEL计时,在PCIE中保留(为0)。 |
bit11 | 已发送目标异常中断,当充当完成者的功能通过发送完成者异常中断完成状况到请求者要求终止请求时,设置该比特。默认值为0。 |
bit12 | 已接收目标异常中断,当请求者收到一个待完成者异常中断完成状况的完成时,设置该比特,默认值为0。 |
bit13 | 已接收主控器异常中断,当请求者收到一个带未受支持的请求完成状况的完成时,设置该比特,默认值为0。 |
bit14 | 已发信号系统错误,当功能发送ERR_FATAL或ERR_NONFATAL消息,并且命令寄存器中的SERR允许比特设为1时,设置该比特,默认值为0。 |
bit15 | 已发现奇偶错误,不论功能的命令寄存器中奇偶错误启动比特状态如何,只要收到一个中毒的TLP,就设置该比特。默认值为0。 |
- Command: PCI设备命令寄存器, 在pci设备使能
pci_enable_device
时会配置该寄存器。主要负责使能或关闭pci设备的I/O访问
、memory访问
和INTx中断
等。
Bit位 | 说明 |
Bit0 | 该位用于控制设别如何响应I/O空间的访问请求,复位后默认为0。 该位为0时,设备不会响应I/O空间访问请求。 该位为1时,设备正常响应I/O空间访问请求。 |
Bit1 | 该位用于控制设别如何响应Memory空间的访问请求,复位后默认为0。 该位为0时,设备不会响应Memory空间访问请求。 该位为1时,设备正常响应Memory空间访问请求。 |
Bit2 | Endpoint:该位决定了设备能否发出Memory读写请求、I/O读写请求。 1:允许 0:不允许(默认) Switch:该位决定了设备能否将Memory读写请求和I/O读写请求转发至上游方向(Upstream Direction)。 Switch的 Downsteam端口收到Memory请求和I/O请求后,应该按照Unsupported Requests(UR)处理。对于收到的 Non-Posted 请求,应该向 Requester 发送一个UR Completion状态位置位的Completion。 该位并不会影响 Completion 的转发,除了Memory读写请求和I/O读写请求,其他类型的请求不受该位控制。 |
Bit3 | PCI专用循环,PCIe不用,默认为0。 |
Bit4 | PCI中存储器写和存储器失效允许,PCIe不用,默认为0。 |
Bit5 | PCI中允许VGA调色板侦测允许,PCIe不用,默认为0。 |
Bit6 | 奇偶错误响应,在状况寄存器中,如果设置了奇偶错误响应比特,且有下列条件之一发生,请求者将设置主控器数据奇偶比特: ①、如果请求者受到一个有错误的完成;②、如果请求者写请求中毒;③、如果清除了奇偶错误比特,则不会设置主控器数据奇偶错误比特。 |
Bit7 | PCI中的步长控制,PCIe不用,默认为0。 |
Bit8 | Endpoint:为1时,设备可以向RC发送ERR_FATAL和ERR_NONFATAL错误消息。 Switch:为1时,设备可以将ERR_FATAL和ERR_NONFATAL错误消息转发到上游总线。 ERR_COR 消息不受该位控制,默认值为0。 |
Bit9 | PCI中启用快速背靠背功能允许,PCIe不用,默认为0。 |
Bit10 | 该位用于控制设备能否产生INTx中断。 1:不允许设备产生INTx中断。 默认值为0。 |
Bit[15:11] | 保留 |
- Class Code: 设备分类信息, 表示pci设备属于哪一种类别。
类 | 说明 | 类 | 说明 |
0x00 | 在定义类代码前建立的功能(PCI2.0前) | 0x0a | 坞站 |
0x01 | 海量存储控制器 | 0x0b | 处理器 |
0x02 | 网络控制器 | 0x0c | 串行总线控制器 |
0x03 | 显示控制器 | 0x0d | 无线控制器 |
0x04 | 多媒体设备 | 0x0e | 智能IO控制器 |
0x05 | 存储器控制器 | 0x0f | 卫星通信控制器 |
0x06 | 桥设备 | 0x10 | 加密/解密控制器 |
0x07 | 简单的通信控制器 | 0x11 | 数据获取和信号处理控制器 |
0x08 | 基本的系统外围设备 | 0x12-0xfe | 保留 |
0x09 | 输入设备 | 0xff | 不舍和任何定义类代码的设备 |
-
Revision ID: 设备版本ID, 表示PCI设备的版本号。该寄存器可以被认为是
Device ID
寄存器的扩展。 只读。 -
BIST: (
Built-In Self-Test
)可选,用于内部自检。
Bit位 | 说明 |
Bit[3:0] | 完成代码,为0表示成功完成;非0表示发生了与特定功能有关的错误 |
Bit[5:4] | 保留 |
Bit6 | 开始BIST(Start BIST),向该比特写入1,表示开始该功能的BIST。完成后,该功能将自动复位该比特。如果BIST不能在2s内完成,软件将不能执行该功能。 |
Bit7 | 具有BIST功能,如果功能有BIST,将返回1,否则返回0。 |
- Header type: PCI设备头类型寄存器。
Bit位 | 说明 |
Bit[6:0] | 0:PCIE EP设备(Non-Bridge Function) 1:PCIE 桥设备(PCI-to-PCI Bridge) 2:PCIE CardBus桥设备(CardBus Bridge) |
bit7 | 0:单功能设备 1:多功能设备 |
- Lantency Timer: 在PCI总线中,多个设备共享同一条总线带宽,该寄存器用来控制PCI设备占用PCI总线的时间。PCIe设备不需要使用该寄存器,该寄存器的值必须为0。因为PCIe总线的仲裁方法与PCI总线不同,使用的连接方法也与PCI总线不同。
- Cache line size: cache缓存大小。对于PCIe设备,该寄存器的值无意义。
- Base Address register: BAR地址寄存器负责PCI设备内部空间的映射,下一节重点介绍;
- Expansion Rom Base Address: 扩展ROM映射基地址寄存器。分配给ROM使用,用于PCI设备在处理器还没有运行操作系统之前,完成基本的初始化设置。
其他寄存器不在列举,后期用到再补充。具体可查看手册《PCI Express Base Specification Revision 3.0
》。
2、BAR配置空间
对Endpoint Configuration(Type 0),提供了最多6个BAR,而对Switch(Type 1)来说,只有2个。如果某个设备的BAR没有被全部使用,则对应的BAR应被硬件全被设置为0。
系统启动后,CPU读取EP/Switch
所需PCI域空间的大小、属性(出厂时已固定写入BAR寄存器、只读),并分配对应的系统内存空间,将root complex
里申请的PCI域地址空间的基地址
和大小
保存在BAR寄存器。该地址空间需要映射到IO地址空间里或者内存地址空间之后CPU才能使用 ;
对于被使用的BAR来说,其部分低比特位是不可以被软件操作的,只有其高比特位才可以被软件操作。而这些不可操作的低比特决定了当前BAR支持的操作类型和可申请的地址空间的大小。
3、PCIe工作过程
PCIe上电后主要经历链路训练、枚举扫描、配置BAR空间三个过程。
3.1、链路初始化和训练
物理层实现链路训练(Link Training
)和链路初始化(Link Initialization
)的功能,这一般是通过链路训练状态机(Link Training and Status State Machine
,LTSSM
)自动完成。
链路训练主要为确认PCIe设备的基本属性:链路宽度(X1、X2、X4…)、速率(Link Data Rate
)、通道位置翻转(Lane Reversa
l)、信号极性翻转(Polarity Inversion
)、位锁定且时钟恢复(Bit Lock per Lane
)、字符Gen1/2块锁定(Symbol lock or Block alignment per Lane
)、通道对齐(Lane-to-Lane De-Skew Within a Multi-Lane Link
)等。
具体细节可阅读:PCIe物理层链路训练和初始化(详细)总结附图文解析-PCIe专题知识(三)
3.2、枚举扫描
PCIe的Switch(Type1)
配置空间字段含义的补充:
Subordinate Bus Number
设备最后一级总线号,即该Switch子树下最大总线号Secondary Bus Number
当前总线号Primary Bus Number
上一级总线号
CPU需知道系统中有那些PCIe设备,并且为每个设备分配总线号。而Host对PCIe设备扫描采用了深度优先算法,其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只访问一次。
PCIe设备枚举过程如下:
1、在处理器系统中,一般将Root complex
中与Host Bridge
相连接的PCI总线命名为PCIe Bus 0
,系统将初始化Bus 0
配置空间并将寄存器Sec设为0,由于无法确定Bus 0
下挂载PCIe设备情况,暂将Sub设为0xFF;
2、PCIe Host主桥扫描Bus 0
上的设备,主桥发现Bridge 1
后,将Bridge1
下面的Pcie Bus
定为 Bus 1
,系统将初始化Bridge 1
的配置空间,并设置Pri = 0、Sec = 1(表明Bridge1 的上游总线是0,下游总线是1)、Sub暂时设置为0xFF;
3、系统继续扫描Bus 1
下设备,通过该设备的获取配置空间,发现这是个Switch
设备。系统将该设备Bridge 1
下的PCIe Bus
定为Bus 2
,并设置该桥Pri = 1、Sec = 2、Sub = 0xFF;
4、系统继续扫描Bus 2
下设备,系统将该设备Bridge 2
下的PCIe Bus
定为Bus 3
,并设置该桥Pri = 2、Sec = 3;扫描Bus 3
下设备,通过该设备的获取配置空间,发现这是个Ep
设备,故设置Sub = 3;
5、系统继续扫描Bus 2
下设备,系统将该设备Bridge 3
下的PCIe Bus
定为Bus 4
,并设置该桥Pri = 2、Sec = 4;扫描Bus 4
下设备,通过该设备的获取配置空间,发现这是个Ep
设备,故设置Sub = 4;
6、系统继续扫描Bus 0
下设备,通过该设备的获取配置空间,发现这是个Switch
设备。系统将该设备Bridge 1
下的PCIe Bus
定为Bus 4
,并设置该桥Pri = 0、Sec = 5、Sub = 0xFF;
… …
3.3 、配置BAR空间
作用: 配置PCIe设备的基地址寄存器,给PCIe分配地址空间;
Eg: 系统软件为PCIe设备分配映射Memory空间:
-
设备上电时,系统软件向该BAR写全1,再读回该BAR寄存器,如果返回全0,表明该BAR没有实现;
-
如果返回非0(如下图所示:
0xFFFF F000
),表明这个BAR对应了一个32位Memory空间,0xFFFF F000
可操作的最低位为12,则该BAR可申请地址空间大小为4KB
(2^12
); -
系统软件在系统
Memory
空间中映射4KB的空间,并将分配的基地址写入BAR寄存器的高20位; -
CPU若想访问该PCIe设备空间,只需要访问对应的内存空间即可。
参考:FPGA-PCIe解读、老男孩读PCIe介绍系列、《PCI EXPRESS系统体系结构标准教材》