PCIe配置空间

23 篇文章 45 订阅

PCIe概述

PCI Express,是计算机总线PCI的一种,它沿用现有的PCI编程概念及通信标准,但建基于更快的串行通信系统。
PCIE总线使用的是高速差分总线,并采用端到端的连接方式, 现在的高速总线基本上都是串行总线,这样可以使用更高的时钟频率。

当前pcie协议支持到5.0版本,不同PCIe版本对应的传输速率如下:

PCIe 版本编码传输速率(GT/S)x4吞吐量(MB/s)
1.08b/10b2.51
2.08b/10b52
3.0128b/130b8~4
4.0128b/130b16~8
5.0128b/130b32~16

pcie总线的拓扑结构

在这里插入图片描述
PCIe采用的是树形拓扑结构, 它的体系架构一般由root complex,switch,endpoint等类型的PCIe设备组成
root complex: 根桥设备,是PCIe最重要的一个组成部件; root complex主要负责PCIe报文的解析和生成。RC接受来自CPU的IO指令,生成对应的PCIe报文,或者接受来自设备的PCIe TLP报文,解析数据传输给CPU或者内存。
switch: PCIe的转接器设备,目的是扩展PCIe总线。和PCI并行总线不同,PCIe的总线采用了高速差分总线,并采用端到端的连接方式, 因此在每一条PCIe链路中两端只能各连接一个设备, 如果需要挂载更多的PCIe设备,那就需要用到switch转接器。switch在linux下不可见,软件层面可以看到的是switch的上行口(upstream port, 靠近RC的那一侧)和下行口(downstream port)。
在这里插入图片描述
一般而言,一个switch 只有一个upstream port, 可以有多个downstream port.

PCIe endponit: PCIe终端设备,是PCIe树形结构的叶子节点。比如网卡,NVME卡,显卡都是PCIe ep设备。
在这里插入图片描述
lspci -tv命令可以显示pcie的总线拓扑,如上图所示, 一个PCIe设备的ID由以下几个部分组成:
以0000:00:00.0为例,分别对应PCI域,总线号,设备号,功能号

  1. PCI域:PCI域ID,目的是为了突破pcie256条总线的限制。
  2. PCI总线号:pci设备的总线ID,占用8位,所以PCIe总线最多支持256个子总线。
  3. PCI设备号:指定总线上,pci的设备ID,Device Number占用5位, 所以每个子总线最多支持32个设备
  4. PCI功能号:指定设备上,pci设备的功能ID, 一个pci 物理设备可以实现多个功能设备,且逻辑功能相互独立,Function Number占用3位,所以每个物理设备最多支持8个功能。

BDF(Bus,device,function)构成了每个PCIe设备节点的身份标识。

PCIe配置空间

PCI有三个相互独立的物理地址空间:memory地址空间、I/O地址空间和配置空间。这三个地址空间都是采用唯一的地址进行寻址,比如我们使用地址0x100时需要指定这个地址在哪个地址空间,配置空间,I/O地址空间和memory地址空间的0x100偏移,对应的是不同的存储位置。
我们可以读取配置空间获得设备的信息,也可以通过配置空间来配置设备,通过pci设备的id和配置空间的偏移地址, 软件可以来访问具体的寄存器。
PCIe设备的每一个功能(function)都对应一个独立的配置空间, pcie的配置空间布局如下:
在这里插入图片描述
如上图所示,pci的配置空间是256字节,其中64字节是标准配置空间header, 后面的192字节是Capability结构, 展示pci能提供的能力。 为了兼容PCI,PCIe的配置空间前256字节与PCI保持一致,256~4096字节是pcie 扩展配置空间,包含pcie的扩展能力如AER。

访问PCIe配置空间不能通过直接读写系统总线实现,因为系统总线上看到的是CPU地址。在PCIe标准中,访问PCIe配置空间的是cfg tlp(configuration transaction layer packet)。cfg tlp又分为type 0和type 1,type 1用来访问PCIe桥,type 0访问端点设备。综上所述,要访问SW的配置空间,就要发起cfg type1 tlp;要访问EP配置空间,就要发起cfg type0 tlp。每种cfg tlp又分read(rd)和write(wr),排列组合一下,cfg tlp就有四种形式:type 0 rd、type 0 wr、type 1 rd、type 1 wr。

综合地址编码和配置空间的介绍,这里给出每个function在PCI域的配置基址:cfg_base[27:20] = Bus Number,cfg_base[19:15] = Device Number,cfg_base[14:12] = Function Number。

需要特别注意的是,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。

1. PCI标准配置空间头(0 ~ 64 bytes)

PCI标准配置空间分type0和type1两种。type0主要是针对PCI的endpoint设备,type1主要是针对PCI bridge, switch。
在这里插入图片描述
如上图所示,type0和type1有一些共同的寄存器描述。
Device ID: 设备ID, 表示该PCI设备的设备号,只读。
Vendor ID: 厂商ID, 表示生产该设备的厂商的编号,只读。
Status: pci设备状态寄存器,用于保存pci设备的状态,如中断状态或运行产生错误时的状态。
在这里插入图片描述

Command: PCI设备命令寄存器, 在pci设备使能pci_enable_device时会配置该寄存器。主要时负责使能或关闭pci设备的I/O 访问,memory访问和INTx中断等。
在这里插入图片描述
Class Code: 设备分类信息, 表示pci设备属于哪一种类别,如网卡,存储卡,显卡等。需要重点关注的一个寄存器,之前定位过一个问题,pci设备资源分配失败,就是因为将class code设置为0, 而那张卡是pcie 网卡, class code应该设置为2。
Revision ID: 设备版本ID, 表示PCI设备的版本号。该寄存器可以被认为是Device ID寄存器的扩展。 只读。
BIST: 可选,用于内部自检。
Header type: PCI设备头类型寄存器,表示该设备时pci EP设备还是PCI 桥设备。PCI配置空间时type0还是type1就是由该寄存器定于。
Lantency Timer: 在PCI总线中,多个设备共享同一条总线带宽,该寄存器用来控制PCI设备占用PCI总线的时间。PCIe设备不需要使用该寄存器,该寄存器的值必须为0。因为PCIe总线的仲裁方法与PCI总线不同,使用的连接方法也与PCI总线不同。
Cache line size: cache缓存大小。对于PCIe设备,该寄存器的值无意义。
Expansion Rom Base Address: 扩展ROM映射基地址寄存器。分配给ROM使用,用于PCI设备在处理器还没有运行操作系统之前,完成基本的初始化设置。
Base Address register: BAR地址寄存器负责PCI设备内部空间的映射。
在这里插入图片描述
type0有6个32bit的BAR寄存器,type1与2个32bit的BAR寄存器。每一个BAR地址对应一个地址空间。
在BAR寄存器有些bit是只读的,是PCI设备在出厂前就固定好的bit,写全1进去,如果值保持不变,就说明这些bit是厂家固化好的,这些固化好的bit提供了这块内部空间的一些信息。

举个例子:
上电时,系统软件首先会读取PCIe设备的BAR0,得到数据:
在这里插入图片描述
然后系统软件往该BAR0写入全1,得到:
在这里插入图片描述
低12bit没变,表明该设备空间大小是4KB(2的12次方),BAR地址的低4位表明了该存储空间的一些属性([0]: IO映射还是memory映射,[2:1]32bit地址还是64bit地址,[3]能否可预取)。
然后系统软件根据这些信息,在系统内存空间找到这样一块地方来映射这4KB的空间,把分配的基地址写入到BAR寄存器。

BAR地址寄存器负责PCI设备内部空间的映射, 有了这个映射,CPU可以做到对pcie设备空间的访问。
比如CPU想去读PCIe设备的数据,系统启动时通过BAR地址把PCIe设备空间映射到内存空间,CPU要访问该PCIe设备空间,只需访问对应的内存空间。CPU发出一个物理地址,RC检查该地址,如果发现该内存空间地址是某个PCIe设备空间的映射,就会触发其产生TLP,去访问对应的PCIe设备,读取或者写入PCIe设备。

Capbility Pointer: PCI capbility的地址偏移, capbility用于表示pci设备支持的能力。该寄存器存放Capabilities 结构链表的头指针。在一个PCIe 设备中,可能含有多个Capability 结构,这些寄存器组成一个链表:
在这里插入图片描述

Interrupt Pin: PCI设备中断引脚,支持INTX A/B/C/D四个中断引脚。
Interrupt line: 表示当前PCI设备使用的中断号。

type0 独有的寄存器:
CardBus CISpointer: 只读,可选,用于表明访问CIS(card info structure)的地址空间, 通常不会涉及。
Subsystem ID/ subsystem Vendor ID: 子系统和子厂商ID,可以结合Device ID和Vendor ID来组成完成的PCI设备标识。
Max_lat: 设备期望的最大延时,只读。
Min_Gbt: 设备期望的最小延时,只读。

type1 独有的寄存器:
Primary Bus Number: 表示PCI设备挂在的PCI总线号。
Subordinate Bus Number: PCI桥可以管理其下的PCI总线子树。其中Subordinate Bus Number寄存器存放当前PCI子树中,编号最大的PCI总线号。
Secondary Bus Number: 存放当前PCI桥Secondary Bus使用的总线号,这个PCI总线号也是该PCI桥管理的PCI子树中编号最小的PCI总线号
Secondary Latency Timer: PCI桥下游的延时寄存器,和Latency Timer寄存器的含义相近
I/O base: 表示IO寻址的基地址, 低4bit只读,所以PCI设备默认IO寻址4K对齐,高4bit可写。
I/O limit: IO寻址的上限,高4bit可写,低4bit为全F,所以io寻址上限是I/O limit地址 + 4K.
Secondary status: 保存PCI下游总线和设备的状态。
Memory Base: 表示memory寻址的基地址。
Memory Limit: 表示memroy寻址的上限,和IO limit类似。
Prefetchable Memory Base: 可预取内存的基地址
Prefetchable Memory Limit: 可预取内存寻址的上限。
Bridge Control Register:管理PCI桥的Secondary Bus, 可以控制 Secondary Bus的 Reset。

2. PCI capbility结构(64 ~ 256bytes)

这段空间主要存放一些与MSI/MSI-X中断机制和电源管理相关的capbility。
在内核include/uapi/linux/pci_regs.h归纳了capabilityID和各个capability名称的对应关系:

3. PCIe 扩展配置空间(256 ~ 4K bytes)

这段空间主要存放PCIe独有的一些capbility结构,如AER, SR-IOV等。

PCIE配置空间的访问

CPU可以通过访问BAR地址读取PCIe的设备空间,但是我们需要读取到配置空间才能获取BAR,那么怎么访问PCIe的配置空间呢?
ARM使用ECAM的方式访问PCIe配置空间。ECAM是一个将配置空间映射到MEMORY空间的规则。硬件根据ECAM的方式将某个Memory空间映射给PCI配置空间,CPU访问对应的memory空间即可以操作PCIe配置空间。
映射的地址定义如下:
在这里插入图片描述
PCIe总线最多支持256个子总线,每个子总线最多支持32个设备,每个设备最多支持8个功能, 每个配置空间是4KB,所以需要映射256 buses × 32 devices × 8 functions × 4 KiB = 256 MiB 空间的大小。

在ACPI规范中,需要通过MCFG表上报ECAM的地址映射
在这里插入图片描述
完成映射后,CPU发出的地址如果落在ECAM的范围内, 根据对应的bdf就可以访问到对应ep的配置空间了。
Linux内核中的MCFG实现读/写分别对应函数pci_read_config_byte/word/dword 和 pci_write_config_byte/word/dword

type0/type1 cfg TLP

Type0还是Type1是由事务层包(TLP)包头中的Type Field所决定的,而读还是写则是由TLP包头中的Format Field所决定的。分别以下两张图所示:
在这里插入图片描述
在这里插入图片描述
当Root发起配置空间读写请求时,相应的桥首先检查请求的BDF中的Bus号是否与自己的下一级总线号(Secondary Bus Number)相等,如果相等,则先将Type1转换为Type0,然后发给下一级(即Endpoint)。

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

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

一个简单的例子如下图所示:
在这里插入图片描述

参考资料

PCI桥与PCI设备的配置空间
老男孩读PCIe之六:配置和地址空间
PCI.EXPRESS系统体系结构标准教材

[PCIe扫盲——Type0 & Type1 型配置请求](http://blog.chinaaet.com/justlxy/p/5100053322)
  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PCIe配置空间寄存器是PCI Express总线设备中的一种特殊类型的寄存器,用于配置和管理设备的功能和属性。每个PCIe设备都有一个配置空间,该空间包含了设备的配置信息和功能寄存器,这些信息和寄存器可以被系统软件读取和写入,用于进行设备的初始化和控制。 配置空间寄存器使用了标准的PCI配置空间寄存器格式,包括设备ID、供应商ID、命令和状态寄存器等。通过读取和设置这些寄存器的值,系统软件可以访问和控制PCIe设备的各种功能。 配置空间寄存器的结构和布局是由PCIe规范定义的,包含了设备的通用配置数据、功能寄存器和扩展配置区域。其中通用配置数据包括了设备的基本信息,如设备类型、供应商标识、设备标识等。功能寄存器用于控制和管理设备的功能,如启用或禁用设备、设置中断和总线驱动程序等。扩展配置区域用于存储设备特定的配置信息,各个设备的扩展配置区域的结构和内容是不同的,由设备厂商自行定义。 系统软件可以通过访问PCIe配置空间寄存器来获取设备的配置信息,如设备名称、设备类型、硬件ID等,还可以进行设备的初始化和配置,如设定中断线路、分配资源等。一般情况下,操作系统和驱动程序会使用配置空间寄存器来与PCIe设备进行通信和管理,以实现设备的正常工作和使用。 总之,PCIe配置空间寄存器是PCI Express总线设备中用于配置和管理设备的一种寄存器,通过读取和设置其中的值,系统软件可以访问和控制设备的各种功能。这些配置空间寄存器的结构和布局是由PCIe规范定义的,不同设备的配置信息和功能也各不相同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值