LJgibbs · 2022年01月21日

PCIe扫盲——BDF与配置空间/配置空间的读写机制/Type0 & Type1 型配置请求

写在前面

笔者在工作中需要包个 PCIe wrapper,正在努力飞快学习 PCIe ing.
本文系转载,略做格式调整与增加解释(使用斜体表示),转自:
PCIe扫盲--BDF与配置空间-Felix-电子技术应用-AET-中国科技核心期刊-最丰富的电子设计资源平台
PCIe扫盲--配置空间的读写机制-Felix-电子技术应用-AET-中国科技核心期刊-最丰富的电子设计资源平台
PCIe扫盲--Type0 & Type1 型配置请求

转载正文

连载目录篇:http://blog.chinaaet.com/justlxy/p/5100053328

BDF与配置空间

前面的文章中介绍过,每一个PCIe设备可以只有一个功能(Function),即Fun0。也可以拥有最多8个功能,即多功能设备(Multi-Fun)。

不管这个PCIe设备拥有多少个功能,其每一个功能都有一个唯一独立的配置空间(Configuration Space)与之对应。

和PCI总线一样,PCIe总线中的每一个功能(Function)都有一个唯一的标识符与之对应。

这个标识符就是BDF(Bus,Device,Function),PCIe的配置软件(即Root的应用层,一般是PC)应当有能力识别整个PCIe总线系统的拓扑逻辑,以及其中的每一条总线(Bus),每一个设备(Device)和每一项功能(Function)。

在BDF中,Bus Number占用8位,Device Number占用5位,Function Number占用3位。显然,PCIe总线最多支持256个子总线,每个子总线最多支持32个设备,每个设备最多支持8个功能。

PCIe总线采用的是一种深度优先(Depth First Search)的拓扑算法,且Bus0总是分配给Root Complex。Root中包含有集成的Endpoint和多个端口(Port),每个端口内部都有一个虚拟的PCI-to-PCI桥(P2P),并且这个桥也应有设备号和功能号。

需要注意的是,每个设备必须要有功能0(Fun0),其他的7个功能(Fun1~Fun7)都是可选的。

一个简单的例子如下图所示:
image.png
注:关于PCIe总线的拓扑逻辑会在后面的文章中进行详细地介绍。

前面的关于PCI总线的文章介绍过PCI总线的配置空间,PCIe总线为了兼容这些PCI设备,几乎完整的保留了PCI总线的配置空间。并将配置空间扩展到4KB,用于支持一些PCIe总线中新的功能,如PCI Express Capability、Power Management和MSI/MSI-X等。

下图是从PCI总线中继承过来的配置空间:
image.png
下图是PCIe新增的配置空间的示意图:
image.png

配置空间的读写机制

需要特别注意的是,PCIe的Spec中明确规定只有Root有权限发起配置请求(Originate Configuration Requests),也就是说PCIe系统里面的其他设备是不允许去配置其他设备的配置空间的,即peer-to-peer的配置请求是不允许的。并且配置请求的路由(Routing)方式只能是采用BDF(Bus,Device,Function)。

处理器一般不能够直接发起配置读写请求,因为其只能产生Memory Request和IO Request。这就意味着Root必须要将处理器的相关请求转换为配置读写请求。

针对传统的PCI设备(Legacy PCI),采用的是IO间接寻址访问(IO-indirect Accesses);针对PCIe设备,采用的是Memory-Mapped Accesses。

关于Legacy PCI的IO-indirect Accesses,在前面介绍PCI的文章中实际上已经讲过了。可以参考如下两篇文章:

PCIe扫盲——PCI总线的地址空间分配:http://blog.chinaaet.com/justlxy/p/5100053219
PCIe扫盲——PCI总线配置周期产生和配置寄存器:http://blog.chinaaet.com/justlxy/p/5100053220
前面的文章还介绍过,Root和Switch的每一个端口中都包含一个P2P桥,并且知道桥的配置空间头(Configuration Space Header)是Type1型的。如下图所示:
image.png
每个Type1型的Header中都包含最后一级总线号(Subordinate Bus Number)、下一级总线号(Secondary Bus Number)和上一级总线号(Primary Bus Number)等信息。当配置请求进行BDF路由的时候,正是依靠这些信息来确定要找的设备的。一个简单地例子如下图所示:
image.png
注:上面的例子是整个PCIe总线系统中只有一个Root的情况,实际上PCIe Spec还允许总线系统中存在多个Root(即Multi-Root)。关于Multi-Root,这里就不详细地介绍了,有兴趣地可以自行阅读PCIe的Spec。

Type0 & Type1 型配置请求

前面的文章中介绍过有两种类型的配置空间,Type0和Type1,分别对应非桥设备(Endpoint)和桥设备(Root和Switch端口中的P2P桥)。

Type0还是Type1是由事务层包(TLP)包头中的Type Field所决定的,而读还是写则是由TLP包头中的Format Field所决定的。分别以下两张图所示:
image.png
之前的文章中强调过,PCIe中只有Root才可以发起配置空间读写请求,并且我们知道Root的每个端口中都包含有一个P2P桥。

当Root发起配置空间读写请求时,相应的桥首先检查请求的BDF中的Bus号是否与自己的下一级总线号(Secondary Bus Number)相等,如果相等,则先将Type1转换为Type0,然后发给下一级(即Endpoint)。

如果不相等,但是在自己的下一级总线号(Secondary Bus Number)和最后一级总线号(Subordinate Bus Number)之间,则直接将Type1型请求发送给下一级。如果还是不相等,则该桥认为这一请求和自己没什么关系,则忽略该请求。

注:Root最先发送的配置请求一定是Type1型的。非桥设备(Endpoint)会直接忽略Type1型的配置请求。

一个简单的例子如下图所示:
image.png
注:原计划中的“PCIe扫盲——PCIe总线的拓扑逻辑”这一篇取消了。大家如果有兴趣的,可以自行阅读PCIe Spec或者MindShare的书籍。

版权声明

版权声明:本文为 AET 博主「Felix」的原创文章,转载请附上原文出处链接及本声明。
原文链接:http://blog.chinaaet.com/justlxy/p/5100053328

转载自:知乎
作者:Felix

推荐阅读

更多招聘及面经请关注FPGA的逻辑
推荐阅读
关注数
10614
内容数
577
FPGA Logic 二三事
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息