PCI、PCIe 一篇搞定 |
您所在的位置:网站首页 › pci到isa桥 › PCI、PCIe 一篇搞定 |
文章目录
缩略词历史PCI从 PCI 到 PCIePCIe 和 PCI 差异PCIePCI 细节HOST 主桥PCI 总线PCI 设备HOST 处理器PCI 总线的负载PCI 总线的信号定义地址和数据信号接口控制信号仲裁信号中断请求信号
PCI 总线的存储器读写总线事务PCI 总线事务的时序Posted 和 Non-Posted 传送方式HOST 处理器访问 PCI 设备PCI 设备读写主存储器
PCI 总线的中断机制中断请求的同步
PCI 总线的桥与配置存储器域与 PCI 总线域HOST 主桥PCI 设备配置空间的访问机制存储器域地址空间到 PCI 总线域地址空间的转换x86 处理器的 HOST 主桥PCI 桥PCI Agent 设备的配置空间PCI 桥的配置空间
PCI 总线的配置PCI 总线的数据交换PCI 设备 BAR 空间的初始化存储器地址与 PCI 总线地址的转换PCI 设备 BAR 寄存器和 PCI 桥 Base、Limit 寄存器的初始化
PCI 设备的数据传递处理器到 PCI 设备的数据传送PCI 设备的 DMA 操作
与 Cache 相关的 PCI 总线事务Cache 一致性的基本概念PCI 设备对不可 Cache 的存储器空间进行 DMA 读写PCI 设备对可 Cache 的存储器空间进行 DMA 读写
预读机制指令预读数据预读PCI 总线的预读机制
PCIe 细节PCIe 总线的基础知识端到端的数据传递PCIe 总线使用的信号PCIe 总线的层次结构PCIe 链路的扩展
PCIe 体系结构的组成部件PCIe 体系结构的组成部件基于 PCIe 总线的通用处理器结构RC 的组成结构SwitchVC 和端口仲裁
PCIe 设备的扩展配置空间PCIe 总线的事务层TLP 格式TLP 的路由基于地址的路由基于 ID 的路由隐式路由消息请求报文INTx 中断消息报文
PCIe 总线的数据链路层与物理层物理层简介PCIe 链路的差分信号
PCIe 总线的链路训练与电源管理流量控制流量控制的基本原理
MSI 和 MSI-X 中断机制
缩略词
缩写全拼解释ISAIndustry Standard Architecture工业标准结构PCIPeripheral Component Interconnect外围器件互联PCIePCI ExpressPCI-SIGPCI 特殊兴趣组织
历史
PCIe 是继 ISA 和 PCI 总线之后的第三代 I/O 总线,最开始被称为 3GIO,由 Intel 在 2001 年提出,2002 年 PCI-SIG 审核后公布了第一版规范,并更名为 PCI Express。 第一代总线一般指 ISA、EISA、VESA 和 Micro Platforms,第二代总线一般指 PCI、AGP 和 PCI-X。 由于 PCIe 是从 PCI/PCI-X 继承发展而来,PCIe 在软件上几乎是全完兼容 PCI/PCI-X 的。在硬件层面上,可以借助 PCIe to PCI/PCI-X 桥来与其完成对接。 —— PCIe扫盲——PCIe简介 —— 《PCI Express 体系结构解读》 —— 深入PCI与PCIe之一:硬件篇 PCIPCI 标准的特点 它是并行总线 在一个时钟周期内 32 bit 同时被传输,引脚定义如下![]() PCI 后期越来越不能适应高速发展的数据传输需求,PCI-X 和 AGP 走了两条不同的路,PCI-X 不断提高时钟频率,AGP 通过在一个时钟周期内传输两次数据来提速(时钟上下沿进行数据传输,类似 DDR)。 随着频率的提高,PCI 并行传输干扰异常严重,甚至成为不可跨越的坎。 从 PCI 到 PCIe 最大的改变是由并行改为了串行,通过差分信号传输 ![]() PCIe 1.0 和 2.0 采用 8b/10b 编码方式,这意味着一个字节(8bit)需要用(10bit)传输,这就是为什么 2.5GHz 时钟,每时钟 1b 数据。结果不是 312.5MB/s 而是 250MB/s。 PCIe 3.0 和 4.0 采用 128b/130b 编码,减少了浪费(overhead),所以才能在 8GHz 时钟下带宽达到 1GB/s(而不是 800MHB/s)。 PCI 总线作为处理器系统的局部总线,其主要目的是为了连接外部设备,而不是作为处理器的系统总线连接 Cache 和 内存。 PCI 总线作为系统总线的延伸,其设计考虑了许多与处理器相关的内存,如处理器的 Cache 一致性。 HOST 主桥是一个很特别的桥片,用来隔离存储器域和 PCI 总线域,管理 PCI 总线域,并完成处理器与 PCI 设备间的数据交换。处理器与 PCI 设备间的数据交换主要由“处理器访问 PCI 设备的地址空间”和“PCI设备使用 DMA 访问内存”这两部分组成。 每一颗 HOST 主桥都管理一颗 PCI 总线树,在同一颗 PCI 总线树上的所有 PCI 设备属于同一个 PCI 总线域。 在这颗总线树上的所有 PCI 设备的配置空间都由 HOST 主桥通过配置读写总线周期访问。 如果 HOST 主桥支持 PCI V3.0 规范的 Peer-to-Perr 数据传送方式,那么分属不同 PCI 总线域的 PCI 设备可以直接进行数据交换(PCIe 只有在同一颗树下的才行)。 PCI 总线一个 HOST 主桥管理一颗 PCI 总树,一颗 PCI 总树可能包含多个 PCI 总线。 PCI 总线由 HOST 主桥和 PCI 桥管理。 PCI 设备在 PCI 总线中有三类设备:PCI 主设备、PCI 从设备、桥设备。 (HOST 主桥并不是 PCI 设备(这也是为什么 lspci 命令并不会列出 HOST 主桥设备的原因?)。PCI 规范也没有规定如何设计 HOST 主桥。) 其中 PCI 从设备只能被动地接收来自 HOST 主桥或其它 PCI 设备的读写请求; 而 PCI 主设备可以通过总线仲裁获得 PCI 总线的使用权,主动地向其它 PCI 设备或者内存发起读写请求。 而桥设备的主要作用是管理下游的 PCI 总线,并转发上下游总线之间的总线事务。它包括 PCI 桥、PCI-to-ISA 桥,PCI 桥的存在使 PCI 总线极具扩展性,处理器系统可以使用 PCI 桥进一步扩展 PCI 总线。PCI 桥可以连接两条 PCI 总线,上游 PCI 总线和下游 PCI 总线,这两个总线属于同一个 PCI 总线域,使用 PCI 桥扩展的所有 PCI 总线都属于同一个 PCI 总线域。 其中对 PCI 设备配置空间的访问可以从上游总线转发到下游总线,而数据传送可以双方向进行。 一个 PCI 设备可以既是主设备也是从设备,但在同一时刻,这个 PCI 设备要么是主设备要么是从设备。PCI 总线规范将 PCI 主从设备统称为 PCI Agent 设备。常见的 PCI 网卡、显卡、声卡等设备都是 PCI Agent 设备。 HOST 处理器PCI 总线规定在同一时刻内,在一颗 PCI 总线树上有且只有一个 HOST 处理器。这个 HOST 处理器可以通过 HOST 主桥,发起 PCI 总线的配置请求总线事务,并对 PCI 总线上的设备和桥片进行配置。 在 PCI 总线中,HOST 处理器是一个较为模糊的概念。在 SMP 处理器系统中,所有 CPU 都可以通过 HOST 主桥访问其下的 PCI 总线树,这些 CPU 都可以作为 HOST 处理器。但是值得注意的是,PCI 总线树的实际管理者是 HOST 主桥,而不是 HOST 处理器。 PCI 总线的负载PCI 总线能挂接的负载与总线频率相关,总线频率越高,能挂载的负载越少。 PCI 总线是一条共享总线,在一条 PCI 总线上可以挂接多个 PCI 设备。这些设备通过一系列信号与 PCI 总线相连,这些信号包括:地址/数据信号、控制信号、仲裁信号、中断信号等。 PCI 总线是一个同步总线,每一个设备都具有一个 CLK 信号,其发送设备与接收设备使用这个 CLK 信号进行同步数据传递。PCI 总线可以使用 33MHz 或者 66MHz 的时钟频率,而 PCI-X 总线可以使用 133MHz、266MHz或者533MHz的时钟频率。 除了 RST#、INTA~D#、PME#和 CLKRUN#等信号之外,PCI 设备使用的绝大多数信号都使用这个 CLK 信号进行同步。其中 RST# 是复位信号,而 PCI 设备使用 INTA~D#信号进行中断请求。 地址和数据信号在 PCI 总线中,与地址和数据相关的信号如下 (1)AD[31:0]信号 PCI 总线复用地址与数据信号。PCI 总线事务在启动后的第一个时钟周期传送地址,这个地址是 PCI 总线域的存储器地址或者 I/O 地址;而在下一个时钟周期传送数据。传送地址的时钟周期也被称为地址周期,传送数据的时钟周期也被称为数据周期。PCI 总线支持突发传送,即在一个地址周期之后,可以紧跟多个数据周期(类似于 I2C 的连续读和连续写)。 (2)PAR信号 PCI 总线使用奇偶校验机制,保证地址和数据信号在进行数据传递时的正确性。PAR 信号是 AD[31:0] 和 C/BE[3:0] 的奇偶校验信号。 (3)C/BE[3:0]#信号 PCI 总线复用命令与字节选通引脚。在地址周期中,C/BE[3:0]# 信号表示 PCI 总线的命令。而在数据周期中,C/BE[3:0]# 引脚输出字节选通信号,其中 C/BE3、C/BE2、C/BE1、C/BE0 与数据的字节 3、2、1、0 对应,使用这组信号可以对 PCI 设备进行单个字节、字和双字访问。 以下给出常用的总线事务类型 在 PCI 总线中,接口控制信号的主要作用是保证数据的正常传递,并根据 PCI 主从设备的状态,暂停、终止或者正常完成当前总线事务。其主要信号如下 (1)FRAME# 信号 该信号指示一个 PCI 总线事务的开始与结束。当 PCI 设备获得总线的使用权后,将置该信号有效,即置为低,启动 PCI 总线事务,当结束总线事务时,将置该信号无效,即置为高。PCI 设备(和 HOST 主桥)只有通过仲裁获得当前 PCI 总线的使用权后,才能驱动该信号。 (2)IRDY# 信号 该信号由 PCI 主设备(和 HOST 主桥)驱动,该信号有效时表示 PCI 主设备的数据已经准备完毕。如果当前 PCI 总线事务为写事务,表示数据已经在 AD[31:0] 上有效;如果为读事务,表示 PCI 目标(接收)设备已经准备好接收缓冲,目标(发送)设备可以将数据发送到 AD[31:0] 上。 (3)TRDY# 信号 该信号由目标设备驱动,该信号有效时表示目标设备已经将数据准备完毕。如果当前 PCI 总线事务为写事务,表示目标设备已经准备好接收缓冲,可以将 AD[31:0] 上的数据写入目标设备;如果为读事务,表示 PCI 设备需要的数据已经在 AD[31:0] 上有效。 该信号可以和 IRD# 信号联合使用,在 PCI 总线事务上插入等待周期,对 PCI 总线的数据进行控制。 (4)STOP# 信号 该信号有效时表示目标设备请求主设备停止当前 PCI 总线事务。一个 PCI 总线事务除了可以正常结束外,目标设备还可以使用该信号终止当前 PCI 总线事务。 (5)IDSEL 信号 PCI 总线在进行配置读写总线事务时,使用该信号选择 PCI 目标设备。 IDSEL 信号与 PCI 设备的设备号相关,相当于 PCI 设备配置空间的片选信号。 (6)DEVSEL# 信号 该信号有效时表示 PCI 总线的目标设备准备好,该信号与 TRDY# 信号的不同之处在于该信号有效仅表示目标设备已经完成了地址译码。目标设备使用该信号通知 PCI 主设备,其访问对象在当前 PCI 总线上,但是并不表示目标设备可以与主设备进行数据交换。 PCI 总线规范根据设备的译码速度,将 PCI 设备分为快速、中速、慢速三种。 仲裁信号
PCI 总线提供了 INTA#、INTB#、INTC#、INTD# 四个中断请求信号,PCI 设备借助这些中断请求信号,使用电平触发方式向处理器提交中断请求。当这些中断请求信号为低时,PCI 设备将向处理器提交中断请求;当处理器执行中断服务程序清除 PCI 设备的中断请求后,PCI 设备将该信号置高,结束当前终端请求。 INTx 这组信号为开漏输出,当所有的驱动源不驱动该信号时,该信号由上拉电阻驱动为高。 PCI 总线规定单功能设备只能使用 INTA# 信号,而多功能设备才能使用 INTB#/C#/D# 信号。PCI 设备的这些中断请求信号可以通过某种规则进行线与,之后与中断控制器的中断请求信号线相连。而处理器系统需要预先知道这个规则,以便正确处理来自不同 PCI 设备的中断请求。这个规则也被称为中断路由表。 PCI 总线的存储器读写总线事务总线的基本任务时实现数据传送,将一组数据从一个设备传送到另一个设备,当然总线也可以将一个设备的数据广播到多个设备。在处理器系统中,这些数据传送都要依赖一定的规则,PCI 总线也不例外。 PCI 总线使用单端并行数据线,采用地址译码方式进行数据传递,而采用 ID 译码方式进行配置信息的传递。其中地址译码方式使用地址信号,而 ID 译码方式使用 PCI 设备的 ID 号,包括 Bus Number、Device Number、Function Number 和 Register Number。 PCI 设备只有在系统软件初始化配置空间之后,才能够被其它主设备访问。 当 PCI 设备的配置空间被初始化之后,该设备在当前的 PCI 总线树上将拥有一个独立的 PCI 总线地址空间,即 BAR(Base Address Register)寄存器所描述的空间。 处理器与 PCI 设备进行数据交换,或者 PCI 设备之间进行存储器数据交换时,都将通过 PCI 总线地址完成。 PCI 设备与内存进行 DMA 操作时,使用的也是 PCI 总线域的地址,而不是存储器域的地址。此时 HOST 主桥将完成 PCI 总线地址到存储器域地址的转换。 PCI 总线支持以下几类存储器读写事务 (1)HOST 处理器对 PCI 设备的 BAR 空间进行数据读写,BAR 空间可以使用存储器或 I/O 译码方式。 (2)PCI 设备之间的数据传递。 (3)PCI 设备对主存储器进行读写,即 DMA 读写操作。DMA 读写操作在所有处理器系统中都较为常见,也是 PCI 总线数据传送的重点。在多数情况下,DMA 读写操作结束后将伴随着中断的产生。PCI 设备可以使用 INTA#、INTB#、INTC#、INTD# 信号提交中断请求,也可以使用 MSI 机制提交中断请求。 PCI 总线事务的时序一个 PCI 总线事务的访问时序如下图所示,与 PCI 总线事务相关的控制信号有 FRAME#、IRDY#、TRDY#、DEVSEL# 等信号。 PCI 总线规定了两类数据传送方式,Posted 和 Non-Posted。 Posted 方式指 PCI 主设备向 PCI 目标设备进行数据传递时,当数据到达 PCI 桥后,即由 PCI 桥接管来自上游总线的事务,并将其转发到下游总线。好处是,在数据还没有到达最终的目的地之前,PCI 总线就可以结束当前总线事务,从而在一定程度上解决了 PCI 总线的拥塞问题。 Non-Posted 方式是指 PCI 主设备向 PCI 目标设备进行数据传递时,数据必须到达最终目的地之后,才能结束当前总线事务。缺点是,PCI 总线在没有结束当前事务时必须等待。 PCI 总线规定只有存储器写请求可以采用 Posted 方式,而存储器读请求、I/O 读写请求、配置读写请求只能采用 Non-Posted 方式。 下面以上面结构框图中的 PCI 设备 11 向存储器进行 DMA 写操作为例,说明 Posted 方式实现过程。 PCI 设备 11 进行 DMA 写操作时使用存储器写总线事务,当 PCI 设备 11 获得 PCI 总线 x1 的使用权后,将发送存储器写总线事务到 PCI 总线 x1 上。当 PCI 桥 1 发现这个总线事务的地址不在该桥管理的地址范围内,将首先接收这个总线事务,并结束 PCI 总线 x1 的总线事务。此时 PCI 总线 x1 使用的资源已经被释放,PCI 设备 11 和 PCI 设备 12 可以使用 PCI 总线 x1 进行通信。PCI 桥 1 获得 PCI 总线 x0 的使用权后,将转发这个存储器写总线事务到 PCI 总线 x0 上之后,HOST 主桥 x 将接收这个存储器写总线事务,并最终将数据写入主存储器。 HOST 处理器访问 PCI 设备HOST 处理器对 PCI 设备的数据访问主要包括两方面 处理器向 PCI 设备发起存储器和 I/O 读写请求。(内存空间、I/O 空间)处理器对 PCI 设备进行配置读写。(配置空间)在 PCI 设备的配置空间中,共有 6 个 BAR 寄存器,每一个 BAR 寄存器都与 PCI 设备使用的一组 PCI 总线地址空间对应,BAR 寄存器记录这组地址空间的基地址。将与 BAR 寄存器对应的 PCI 总线地址空间称为 BAR 空间,在 BAR 空间中可以存放 I/O 地址空间,也可以存放存储器(内存)地址空间。注意,在 BAR 寄存器中存放地是 PCI 设备使用的“PCI 总线域”的物理地址,而不是“存储器域”的物理地址。 HOST 处理器访问 PCI 设备 I/O 地址空间的过程,与访问存储器地址空间略有不同。 访问 I/O 地址空间: 有些处理器,如 x86 处理器,具有独立的 I/O 地址空间,x86 处理器可以将 PCI 设备使用的 I/O 地址映射到存储器域的 I/O 地址空间中,之后处理器可以使用 IN、OUT 等指令对存储器域的 I/O 地址进行访问,HOST 主桥会将存储器域的 I/O 地址转换为 PCI 总线域的 I/O 地址,最后使用 PCI 总线的 I/O 总线事务对 PCI 设备的 I/O 地址进行读写访问。在 x86 处理器中,存储器域的 I/O 地址与 PCI 总线域的 I/O 地址相同。 对于没有独立 I/O 地址空间的处理器,如 PowerPC 处理器,需要在 HOST 主桥初始化时,将 PCI 设备使用的 I/O 地址空间映射为处理器的存储器地址空间。PowerPC 处理器对这段“处理器域”的存储器空间进行读写访问时,HOST 主桥会将存储器域的存储器地址转换为 PCI 总线域的 I/O 地址。 访问存储器地址: HOST 处理器在初始化时,需要将 PCI 设备使用的 BAR 空间映射到“存储器域”的存储器地址空间。 HOST 主桥将“存储器域”的读写请求翻译为 PCI 总线的存储器读写总线事务之后,再发送给目标设备。 总结: HOST 主桥相当于一个网关,上面是广域网,下面是局域网HOST 主桥上面是存储器域,下面是 PCI 域;上面是 CPU 的世界,下面是 PCI 的世界;上面通行使用存储器域地址(内存地址),下面通行使用 PCI 地址通信经过网关需要进行地址转换,网关有隔离和转换功能以上面的结构框图为例说明处理器如何通过 HOST 主桥和 PCI 桥 1 对 PCI 设备 11 进行存储器读写操作。当处理器对 PCI 设备 11 进行存储器写操作时,这些数据需要通过 HOST 主桥 x 和 PCI 桥 x1,最终到达 PCI 设备 11,其访问步骤如下 首先处理器将要传递的数据放入通用寄存器中,之后向 PCI 设备 11 映射到的存储器域的地址进行写操作。HOST 主桥 x 接收来自处理器的存储器写请求,之后处理器结束当前存储器写操作,释放系统总线。HOST 主桥 x 将存储器域的存储器地址转换为 PCI 总线域的 PCI 总线地址。并向 PCI 总线 x0 发起 PCI 写请求总线事务。(注意:虽然在许多处理器系统中,存储器地址和 PCI 总线地址完全相等,但其含义完全不同。)PCI 总线 x0 上的 PCI 设备 01、PCI 设备 02 和 PCI 桥 1 将同时监听这个 PCI 写总线事务。最后 PCI 桥 x1 接收这个写总线事务,并结束来自 PCI 总线 x0 的 PCI 总线事务。PCI 桥 x1 向 PCI 总线 x1 发起新的 PCI 总线写总线事务。PCI 总线 x1 上的 PCI 设备 11 和 PCI 设备 12 同时监听这个 PCI 写总线事务。最后 PCI 设备 11 通过地址译码方式接收这个写总线事务,并结束来自 PCI 总线 x1 上的 PCI 总线事务。 PCI 设备读写主存储器PCI 设备与存储器直接进行数据交换的过程被称为 DMA。与其它总线的 DMA 过程类似,PCI 设备进行 DMA 操作时,需要获得数据传送的目的地址和传送大小。 支持 DMA 传递的 PCI 设备可以在其 BAR 空间中设置两个寄存器,分别保存这个目标地址和传送大小。这两个寄存器也是 PCI 设备 DMA 控制器的组成部件。 PCI 设备进行 DMA 操作时,使用的目的地址是 PCI 总线域的物理地址,而不是存储器域的物理地址,因为 PCI 设备并不能识别存储器域的物理地址,而仅能识别 PCI 总线域的物理地址。HOST 主桥负责完成 PCI 总线地址到存储器域地址的转换。 许多处理器允许 PCI 设备访问所有存储器域地址空间,但有些处理器可以设置 PCI 设备所能访问的存储器域地址空间,从而对存储器域地址空间进行保护。 下面以 PCI 设备 11 向主存储器写数据为例,说明 PCI 设备如何进行 DMA 写操作 PCI 设备 11 将存储器写请求发向 PCI 总线 x1,写请求使用的地址为 PCI 总线域的地址。PCI 总线 x1 上的所有设备监听这个请求,因为 PCI 设备 11 是向处理器的存储器写数据,所以 PCI 总线 x1 上的 PCI Agent 设备都不会接收这个数据请求。PCI 桥 x1 发现当前总线事务使用的 PCI 总线地址不是其下游设备使用的 PCI 总线地址,则接收这个数据请求。此时 PCI 桥 x1 将结束来自 PCI 设备 11 的 Posted 存储器写请求,并将这个数据请求推到上游 PCI 总线上,即 PCI 总线 x0 上。PCI 总线 x0 上的所有 PCI 设备包括 HOST 主桥将监听这个请求。PCI 总线 x0 上的 PCI Agent 设备也不会接收这个数据请求,此时这个数据请求将由 HOST 主桥 x 接收,并结束 PCI 桥 1 的 Posted 存储器写请求。HOST 主桥 x 发现这个数据请求是发向存储器的,则将来自 PCI 总线 x0 的 PCI 总线地址转换为存储器地址(liyongjun:应该反过来,先转换,后发现),之后通过存储器控制器将数据写入存储器,完成 PCI 设备的 DMA 写操作。 PCI 总线的中断机制PCI 总线使用 INTA#、INTB#、INTC#、INTD# 信号向处理器发出中断请求。这些中断请求信号为低电平有效,并与处理器的中断控制器连接。在 PCI 体系结构中,这些中断信号属于边带信号(Sideband Signals),PCI 总线规范并没有明确规定在一个处理器系统中如何使用这些信号,因为这些信号对于 PCI 总线是可选信号。PCI 设备还可以使用 MSI 机制向处理器提交中断请求,而不使用这组中断信号。 在 PCI 总线中,INTx 信号是一个异步信号。所谓异步是指 INTx 信号的传递并不与 PCI 总线的数据传送同步,即 INTx 信号的传递与 PCI 设备使用的 CLK# 信号无关。这个“异步”信号给系统软件的设计带来了一定的麻烦。 系统软件程序员需要注意“异步”这种事件,因为几乎所有“异步”事件都会带来系统的“同步”问题。 还是以上面的结构框图为例,当 PCI 设备 11 使用 DMA 方式,将一组数据写入存储器,该设备在最后一个数据离开 PCI 设备 11 的发送 FIFO 时,会认为 DMA 写操作已经完成。此时这个设备将通过 INTx 信号,通知处理器 DMA 写操作完成。 此时处理器(驱动程序的中断服务例程)需要注意,因为 INTx 信号是一个异步信号,当处理器收到 INTx 信号时,并不意味着 PCI 设备 11 已经将数据写入存储器中,因为 PCI 设备 11 的数据传递需要通过 PCI 桥 1 和 HOST 主桥,最终才能到达存储器控制器。 PCI 总线并不知道这个 INTx 信号何时被处理器处理,很有可能处理器已经接收到 INTx 信号,开始执行中断处理程序时,该 PCI 设备还没有完全将数据写入存储器。 因为“PCI 设备向处理器提交中断请求”与“将数据写入存储器”分别使用了两个不同的路径,处理器系统无法保证哪个信息率先到达。从而在处理器系统中存在“中断同步”的问题,PCI 总线提供了以下两种方法解决这个同步问题。 (1)PCI 设备保证在数据到达目的地之后,再提交中断请求。 如果 PCI 设备采用 Posted 写总线事务,PCI 设备无法单纯通过硬件逻辑判断数据什么时候写入到存储器。此时为了保证数据到达目的地后才提交中断请求,PCI 设备需要使用“读刷新”的方法保证数据已经到达目的地。具体方法是向 DMA 写的数据区域发出一个读请求。 PCI 总线规范要求 HOST 主桥和 PCI 桥必须保证这种读操作可以刷新写操作,但问题是,没有多少芯片设计者愿意提供这种机制,因为这将极大地增加他们地设计难度,并且使用这种方法也将增加中断请求地延时。 (2)中断服务例程使用“读刷新”方法 中断服务例程在使用“PCI 设备写入存储器”的这些数据之前,需要对这个 PCI 设备进行读操作。这个读操作也可以强制将数据最终写入存储器,实际上是将数据写入到存储器控制器中。 这种方法也是绝大多数处理器系统采用的方法。程序员在编写中断服务例程时,往往都是先读取 PCI 设备的中断状态寄存器,判断中断产生原因之后,才对 PCI 设备写入的数据进行操作。这个读取中断状态寄存器的过程,一方面可以获得设备的中断状态,另一方面可以保证 DMA 写的数据最终到达存储器。 这里也再次提醒系统程序员注意 PCI 总线的“异步”中断所带来的数据完整性问题。在一个操作系统中,即便中断处理程序没有首先读取 PCI 设备的寄存器,也多半不会出问题,因为在操作系统中,一个 PCI 设备从提交中断到处理器开始执行设备的中断服务例程,所需要的时间较长,处理器系统基本上可以保证此时数据已经写入。但是如果系统程序员不这样做,这个驱动程序依然有 Bug,尽管这些 Bug 因为各种机缘巧合,始终不能够暴露出来,而一旦这些 Bug 被暴露出来将难以定位。 PCI 总线 V2.2 规范还定义了一种新的中断机制,即 MSI 中断机制。MSI 中断机制采用存储器写总线事务向处理器系统提交中断请求,其实现机制是向 HOST 处理器指定的一个存储器地址写指定的数据。这个存储器地址一般是中断控制器规定的某段存储器地址范围,而且数据也是事先安排好的数据,通常含有中断向量号。 HOST 主桥会将 MSI 这个特殊的存储器写总线事务翻译为中断请求,提交给处理器。 PCI 总线的桥与配置在 PCI 体系结构中,含有两类桥,HOST 主桥和 PCI 桥。在每一个 PCI 设备中(包括 PCI 桥)都含有一个配置空间。这个配置空间由 HOST 主桥管理,而 PCI 桥可以转发来自 HOST 主桥的配置访问。在 PCI 总线中,PCI Agent 设备使用的配置空间与 PCI 桥使用的配置空间有些差别,但这些配置空间都是由处理器通过 HOST 主桥管理的。 HOST 主桥管理 PCI 设备的配置空间。 存储器域与 PCI 总线域
主要以 PowerPC 处理器为例说明 HOST 主桥的实现机制,因为在 PowerPC 处理器中,HOST 主桥的实现比较完整,尤其是 PCI 总线域与存储器域的映射关系比较明晰。 访问配置空间,使用 ID 号进行寻址。PCI 设备的 ID 号由总线号(Bus Number)、设备号(Device Number)和功能号(Function Number)组成。 总线号在 HOST 主桥遍历 PCI 总线树时确定。在一棵 PCI 总线树上,有几个 PCI 桥(包括 HOST 主桥),就有几条 PCI 总线。在一棵 PCI 总线树中,总线号由系统软件决定,通常与 HOST 主桥直接相连的 PCI 总线编号为 0,系统软件使用 DFS(Depth-First Search)算法扫描 PCI 总线树上的所有 PCI 总线,并依次进行编号。 一条 PCI 总线的设备号由 PCI 设备的 IDSEL 信号与 PCI 总线地址线的连接关系确定。 功能号与 PCI 设备的具体设计相关。在一个 PCI 设备中最多有 8 个功能设备,而且每一个功能设备都有各自的 PCI 配置空间,不过在绝大多数 PCI 设备中只有一个功能设备。 HOST 主桥使用寄存器号,访问 PCI 设备配置空间的某个寄存器。 在 MPC8548 处理器的 HOST 主桥中,与 PCI 设备配置空间相关的寄存器有 CFG_ADDR、CFG_DATA 和 INT_ACK。系统软件使用 CFG_ADDR 和 CFG_DATA 寄存器访问 PCI 设备的配置空间,而使用 INT_ACK 寄存器访问挂接在 PCI 总线上的中断控制器的中断向量。 MPC8548 处理器使用 ATMU(Address Translation and Mapping Unit)寄存器组进行存储器域到 PCI 总线域,以及 PCI 总线域到存储器域的地址映射。 ATMU 寄存器组由两大组寄存器组成,分别为 Outbound 和 Inbound 寄存器组。其中 Outbound 寄存器组将存储器域的地址转换为 PCI 总线域的地址,而 Inbound 寄存器组将 PCI 总线域的地址转换为存储器域的地址。 只有当 CPU 读写访问的地址访问在 Outbound 寄存器组管理的地址空间之内时,HOST 主桥才能接收 CPU 的读写访问,并将 CPU 在存储器域上的读写访问转换为 PCI 总线域上的读写访问。 CPU 对存储器域的地址访问,首先使用 CCB 总线事务,如果所访问的地址在 Cache 中命中,则从 Cache 中直接获得数据,否则将从存储器域中获取数据。而在绝大多数情况下,外部设备使用的地址空间是不可 Cache 的,所以发向 PCI 设备的 CCB 总线事务通常不会与 Cache 进行数据交换。如果 CCB 总线事务使用的地址在 HOST 主桥的 Outbound 寄存器窗口中命中,HOST 主桥将接收这个 CCB 总线事务,并将其转换为 PCI 总线事务之后,再发送到 PCI 总线上。 x86 处理器的 HOST 主桥x86 处理器使用南北桥结构连接 CPU 和 PCI 设备。其中北桥(North Bridge)连接快速设备,如显卡和内存条,并推出 PCI 总线,HOST 主桥包含在北桥中。而南桥(South Bridge)连接慢速设备。 PCI 总线的电气特性决定了在一条 PCI 总线上挂接的负载个数有限,当 PCI 总线需要连接多个 PCI 设备时,需要使用 PCI 桥进行总线扩展,扩展出的 PCI 总线可以连接其它 PCI 设备,包括 PCI 桥。 在一颗 PCI 总线树上,最多可以挂接 256 个 PCI 设备,包括 PCI 桥。 在一个具体的处理器应用中,PCI 设备通常将 PCI 配置信息存放在 EEPROM 中,PCI 设备进行上电初始化时,将 EEPROM 中的信息读到 PCI 设备的 配置空间中作为初始值。这个过程由硬件逻辑完成,绝大多数 PCI 设备使用这种方式初始化其配置空间。 在 x86 处理器中,系统软件使用 CONFIG_ADDR 和 CONFIG_DATA 寄存器,读取 PCI 设备配置空间的这些初始化信息,然后根据处理器系统的实际情况使用 DFS 算法,初始化处理器系统中所有 PCI 设备的配置空间。 在 PCI Agent 设备的配置空间中包含了许多寄存器,这些寄存器决定了该设备在 PCI 总线中的使用方法。 (1)Device ID 和 Vendor ID 寄存器 这两个寄存器的值由 PCISIG 分配,只读。其中 Vendor ID 代表 PCI 设备的生产厂商,而 Device ID 代表这个厂商所生产的具体设备。如 Intel 公司基于 82571EB 芯片的系列网卡,其 Vendor ID 为 0x8086,而 Device ID 为 0x105E。其中 0x8086 代表 Intel,0x105E 代表 82571EB 网卡芯片。当 Vendor ID 寄存器为 0xFFFF 时,表示为无效 Vendor ID。 (2)Revision ID 和 Class Code 寄存器 只读。Class Code 寄存器记载 PCI 设备的分类,该寄存器由三个字段组成,分别是 Base Class Code、Sub Class Code 和 Interface。其中 Base Class Code 将 PCI 设备分类为显卡、网卡、PCI 桥等设备;Sub Class Code 对这些设备进一步细分;而 Interface 定义编程接口。 (3)Header Type 寄存器 只读,由 8 位组成。 第 7 位为 1 表示当前 PCI 设备是多功能设备,为 0 表示为单功能设备。 第 6~0 位表示当前配置空间的类型,为 0 表示该设备使用 PCI Agent 设备的配置空间,普通 PCI 设备都使用这种配置头;为 1 表示使用 PCI 桥的配置空间,PCI 桥使用这种配置头。 (4)Cache Line Size 寄存器 可读可写。该寄存器由系统软件设置。 该寄存器记录 HOST 处理器使用的 Cache Line 长度。在 PCI 设备运行过程中,只有其硬件逻辑才会使用该寄存器,比如 PCI 设备的硬件逻辑需要得知处理器系统 Cache 行的大小,才能进行存储器写并无效总线事务。 如果 PCI 设备不支持与 Cache 相关的总线事务,系统软件可以不设置改寄存器,此时该寄存器为初始值 0x00。对于 PCIe 设备,该寄存器的值无意义,因为 PCIe 设备在进行数据传送时,在其报文中含有一次数据传送的大小,PCIe 总线控制器可以使用这个“大小”,判断数据区域与 Cache 行的对应关系。 (5)Subsystem ID 和 Subsystem Vendor ID 寄存器 (6)Expansion ROM base address 寄存器 有些 PCI 设备在处理器还没有运行操作系统之前,就需要完成基本的初始化设置,比如显卡、键盘和硬盘等设备。为了实现这个“预先执行”功能,PCI 设备需要提供一段 ROM 程序,而处理器在初始化过程中将运行这段 ROM 程序,初始化这些 PCI 设备。Expansion ROM base address 记载这段 ROM 程序的基地址。 (7)Interrupt Line 寄存器 这个寄存器是系统软件对 PCI 设备进行配置时写入的,该寄存器记录当前 PCI 设备使用的中断向量号,设备驱动程序可以通过这个寄存器,判断当前 PCI 设备使用处理器系统中的哪个中断向量号,并将驱动程序的中断服务例程注册到操作系统中。 liyongjun 总结:操作系统(HOST 主桥)分配给每个 PCI 设备一个中断向量号,将这个中断号写入 PCI 设备配置空间 Interrupt Line 寄存器中。然后驱动程序读取该寄存器,使用 irq_register(),将该中断号和中断服务程序绑定。 目前在绝大多数处理器系统中,并没有使用该寄存器存放 PCI 设备使用的中断向量号。。。 (8)Interrupt Pin 寄存器 这个寄存器保存 PCI 设备使用的中断引脚。PCI 总线提供了四个中断引脚:INTA#、INTB#、INTC# 和 INTD#。Interrupt Pin 寄存器为 1 时表示使用 INTA# 引脚向中断控制器提交中断请求,为 2 表示使用 INTB#。。。 如果 PCI 设备只有一个子设备时,该设备只能使用 INTA#。如果 PCI 设备不使用这些中断引脚,向处理器提交中断请求时,该寄存器的值必须为 0。值得注意的是,虽然在 PCIe 设备中并不含有 INTA~D# 信号,但是依然可以使用该寄存器,因为 PCIe 设备可以使用 INTx 中断消息,模拟 PCI 设备的 INTA~D# 信号。 (9)Base Address Register 0~5 寄存器 该组寄存器简称为 BAR 寄存器,BAR 寄存器保存 PCI 设备使用的地址空间的基地址,该基地址保存的是该设备在 PCI 总线域中的地址。其中每一个设备最多可以有 6 个基址空间,但多数设备不会使用这么多组地址空间。 在 PCI 设备复位后,该寄存器将存放 PCI 设备需要使用的基址空间大小(一般来说 PCI 设备使用 EEPROM 保存 BAR 寄存器的初始值)、这段空间是 I/O 空间还是存储器空间、如果是存储器空间该空间是否可预取。 系统软件对 PCI 总线进行配置时,首先获得 BAR 寄存器中的初始化信息,之后根据处理器系统的配置,将合理的基地址写入相应的 BAR 寄存器中。系统软件还可以使用该寄存器,获得 PCI 设备使用的 BAR 空间的长度,其方法是向 BAR 寄存器写入0xFFFFFFFF,之后再读取该寄存器。 处理器访问 PCI 设备的 BAR 空间时,需要使用 BAR 寄存器提供的基地址。值得注意的是,BAR 寄存器存放的是 PCI 总线域的地址,因此处理器系统并不能直接使用“BAR 寄存器值 + 偏移”的方式访问 PCI 设备的寄存器空间,而需要将 PCI 总线域的地址转换为存储器域的地址。 在 Linux 系统中,一个处理器系统使用 BAR 空间的正确方式如源代码 pciaddr = pci_resource_start(pdev, 1); regs = ioremap(pciaddr, CP_REGS_SIZE);在 Linux 系统中,使用 pci_dev->resource[bar].start 参数保存 BAR 寄存器在存储器域的地址。在编写 Linux 设备驱动程序时,必须使用 pci_resource_start 函数获得 BAR 空间对应的存储器域的物理地址,而不能使用从 BAR 寄存器中读出的地址。 当驱动程序获得 BAR 空间在存储器域的物理地址后,再使用 ioremap 函数将这个物理地址转换为虚拟地址。 Linux 系统直接使用 BAR 空间的方法是不正确的,如源代码 pci_read_config_dword(pdev, 1, &pciaddr); regs = ioremap(pciaddr, BAR_SIZE);在 Linux 中,使用 pci_read_config_dword 函数获得的是 PCI 总线域的物理地址。 在 pci_dev->resource[bar].start 参数中保存的地址已经经过 PCI 总线域到存储器域的地址转换。 (10)Command 寄存器 该寄存器为 PCI 设备的命令寄存器,在初始化时,其值为 0,此时这个 PCI 设备除了能够接收配置请求总线事务之外,不能访问该设备的存储器或者 I/O 空间。 (liyongjun:突然悟了,PCI 设备自身没有内存,所以要借助 HOST 处理器的内存。需要使用多大的内,由 BAR 寄存器告知处理器,处理器会分配给它,并将地址范围再次写入 BAR 寄存器中,只不过这个地址范围被 HOST 主桥转换过,是 PCI 总线域的地址。PCI 设备有数据时,直接使用 DMA 控制器将数据写入到这段内存空间,然后再向处理器发送一个中断,通知处理器去取数据) 系统软件需要合理设置该寄存器之后,才能访问该设备的存储器或者 I/O 空间。在 Linux 中,设备驱动程序调用 pci_enable_device 函数,使能该寄存器的 I/O 和 Memory Space 为之后,才能访问该设备的存储器或者 I/O 地址空间。Command 寄存器的各位的含义如下表 PCI 桥使用的配置空间如下所示,PCI 桥作为一个 PCI 设备,使用的许多配置寄存器与 PCI Agent 的寄存器是类似的,如 Device ID、Vendor ID、Status、Command、Interrupt Pin、Interrupt Line 寄存器等。下面只介绍在 PCI 桥中与 PCI Agent 的配置空间不相同的寄存器。 PCI 总线定义了两类配置请求,一类是 Type 00h 配置请求,另一类是 Type 01h 配置请求。PCI 总线使用这些配置请求访问 PCI 总线树上的设备配置空间,包括 PCI 桥和 PCI Agent 设备的配置空间。 其中 HOST 主桥和 PCI 桥使用 Type 00h 配置请求,访问与 HOST 主桥或者 PCI 桥直接相连的 PCI Agent 设备或者 PCI 桥; 而 HOST 主桥和 PCI 桥使用 Type 01h 配置请求,访问没有与其直接相连(需要至少穿越一个 PCI 桥)的 PCI Agent 设备或者 PCI 桥。 当 x86 处理器对 CONFIG_DATA 寄存器进行读写操作时,HOST 主桥将决定向 PCI 总线发送 Type 00h 配置请求还是 Type 01 配置请求。在 PCI 总线事务的地址周期中,这两种配置请求总线事务的不同反映在 AD[31:0] 信号线上。 处理器首先将目标 PCI 设备的 ID 号保存在 CONFIG_ADDRESS 寄存器中,之后 HOST 主桥根据该寄存器的 Bus Number 字段,决定是产生 Type 00h 配置请求,还是 Type 01h 配置请求。当 Bus Number 字段为 0 时,将产生 Type 00h 配置请求,因为与 HOST 主桥直接相连的总线号为 0;大于 0 时,将产生 Type 01h 配置请求。 ( liyongjun 感悟: 任何一个控制器(PCI 控制器、DDR 控制器、I2C 控制器、SPI 控制器),在 CPU 面前,都被视为一组寄存器。想要让控制器干活,读写它的寄存器就好了。 任何一个外设(PCI 设备、DDR、I2C 设备、SPI 设备),在其控制器面前,都被视为一组寄存器。想要让设备干活,读写它的寄存器就好了。 控制器相当于一个功能函数,寄存就是它对外(CPU)提供的接口。内部函数实现操作外设的功能。 外设相当于一个功能函数,寄存器就是它对外(控制器)提供的接口。内部函数实现从大千世界捞数据的功能(使用 ADC 采集电平,进而将一个个高低电平转换为网络数据、温度数据、距离数据等等)。 因为你无法使用刀子划开控制器或者外设来窥探它内部实现的逻辑(就像合作伙伴不会提供其函数源码),所以控制器或者外设会提供它的接口文档(Datasheet)——寄存器说明、读写时序说明,以及会尽可能充分地描述其内部实现原理(不过,再怎么详尽,也无法百分之百透彻精确地描述其内部构造和运作过程)。不过,尽管这样,Datasheet 仍然是我们能够了解这个器件最好的途径。 ) 在地址周期中,HOST 主桥将 CONFIG_ADDRESS 寄存器的内容复制到 PCI 总线的 AD[31:0] 信号线中。CONFIG_ADDRESS 寄存器与 Type 01h 配置请求的对应关系如下图所示 PCI Agent 设备之间以及 HOST 处理器和 PCI Agent 设备之间可以使用存储器读写和 I/O 读写等总线事务进行数据传送。在大多数情况下,PCI 桥不直接与 PCI 设备或者 HOST 主桥进行数据交换,而仅转发来自 PCI Agent 设备或者 HOST 主桥的数据。 PCI Agent 设备间的数据交换并不是本章讨论的重点。本章侧重讲述 PCI Agent 设备使用 DMA 机制读写主存储器的数据,以及 HOST 处理器如何访问 PCI 设备的 BAR 空间。 PCI 设备 BAR 空间的初始化在 PCI Agent 设备进行数据传送之前,系统软件需要初始化 PCI Agent 设备的 BAR0~5 寄存器和 PCI 桥的 Base、Limit 寄存器。系统软件使用 DFS 算法对 PCI 总线进行遍历时,完成这些寄存器的初始化,即分配这些设备在 PCI 总线域的地址空间。当这些寄存器初始化完毕后,PCI 设备可以使用 PCI 总线地址进行数据传递。 PCI 设备访问存储器域的地址空间,即进行 DMA 操作时,是首先访问该存储器地址空间对应的 PCI 总线地址空间,之后通过 HOST 主桥将这个 PCI 总线地址空间转换为存储器地址空间,再由 DDR 控制器对存储器进行读写访问。 liyongjun疑问:PCI 设备如何知道向哪个存储器域地址空间写数据呢? 想到的答案是:无需知道,它只要知道有一块空间是属于它的,它往里面写内容就行了。让处理器和 HOST 主桥去 care 地址如何转换。 不同的处理器系统采用不同的机制实现存储器域和 PCI 总线域的转换。如 PowerPC 处理器使用 Outbound 寄存器组实现存储器域到 PCI 总线域之间的地址转换,使用 Inbound 寄存器组实现 PCI 总线域到存储器域之间的地址转换。 而 x86 处理器没有这种地址空间域的转换机制,因此从 PCI 设备的角度来看,PCI 设备可以直接访问存储器地址;从处理器的角度来看,处理器可以直接访问 PCI 总线地址空间。但需要注意,在 x86 处理器的 HOST 主桥中仍然有存储器域与 PCI 总线域这个概念,只是在 x86 处理器的 HOST 主桥中,存储器域的存储器地址与 PCI 总线地址相等,这种“简单相等”也是一种映射关系。 存储器地址与 PCI 总线地址的转换假设在一个 32 位处理器中,存储器域的 0xF0000000~0xF7FFFFFF(共 128MB)这段物理地址空间与 PCI 总线的地址空间存在映射关系。 为简化起见,假定在存储器域中只映射了 PCI 设备的存储器地址空间,而不映射 PCI 设备的 I/O 地址空间。而 PCI 设备的 BAR 空间使用 0x70000000~0x77FFFFFF 这段 PCI 总线域的存储器地址空间。 PCI 桥的 Base、Limit 寄存器保存“该桥所管理的 PCI 子树”的存储器或者 I/O 空间的基地址和长度。值得注意的是,PCI 桥也是 PCI 总线上的一个设备,在其配置空间中也有 BAR 寄存器,不过这里不对 PCI 桥的 BAR 寄存器进行说明,因为在多数情况下透明桥并不使用其内部的 BAR 寄存器。 以下面这张图为例,说明 BAR、Base、Limit 寄存器的初始化过程,其中存储器域和 PCI 总线域的映射关系如上图所示。 PCI 设备的数据传递使用地址译码方式,当一个存储器读写总线事务到达 PCI 总线时,在这条总线上的所有 PCI 设备将进行地址译码,如果当前总线事务使用的地址在某个 PCI 设备的 BAR 空间中时,该 PCI 设备将使能 DEVSEL# 信号,认领这个总线事务。 PCI 桥使用的正向译码方式与 PCI 设备使用的正向译码方式有所不同。当一个总线事务是从 PCI 桥的 Primary Bus 到 Secondary Bus 时,PCI 桥使用的正向译码方式与 PCI 设备使用的方式类似。如果该总线事务使用的地址在 PCI 桥任意一个 Memory Base 窗口中命中时,该 PCI 桥将使用正向译码方式接收该总线事务,并根据实际情况决定是否将这个总线事务转发到 Secondary Bus。 下面以图 3-2 所示的处理器系统为例,说明处理器向 PCI 设备 11 进行存储器写的数据传送过程。PCI 设备 11 在 PCI 总线域的地址范围是 0x73000000~0x73FFFFFF。这段空间在存储器域中对应的地址范围是 0xF3000000~0xF3FFFFFF。下面假设处理器使用存储器写指令,访问 0xF3000008 这个存储器地址,其步骤如下 (1)存储器域将 0xF3000008 这个地址发向 HOST 主桥,0xF0000000~0xF7FFFFFF 这段地址已经由 HOST 主桥映射到 PCI 总线域地址空间,所以 HOST 主桥认为这是一个对 PCI 设备的访问。因此 HOST 主桥将首先接管这个存储器写请求。 (2)HOST 主桥将存储器域的地址 0xF3000008 转换为 PCI 总线域的地址 0x73000008,并通过总线仲裁获得 PCI 总线 0 的使用权,启动 PCI 存储器写周期,将这个存储器写总线事务发送到 PCI 总线 0 上。 (3)PCI 总线 0 上的 PCI 桥 1 发现 0x73000008 在自己管理的地址范围内,于是接管这个存储器写请求,并通过总线仲裁逻辑获得 PCI 总线 1 的使用权,并将这个请求转发到 PCI 总线 1 上。 (4)PCI 总线 1 的 PCI 设备 11 发现 0x73000008 在自己的 BAR0 寄存器中命中,于是接收这个 PCI 写请求,并完成存储器写总线事务。 PCI 设备的 DMA 操作下面以图 3-2 所示的处理器系统为例,说明 PCI 设备 11 向存储器进行 DMA 写的数据传送过程。PCI 设备的 DMA 写使用 Posted 方式,而 DMA 读使用 Non-Posted 方式,本节只介绍写。 假定 PCI 设备 11 需要将一组数据发送到 0x10000000~0x1000FFFF 这段存储器域的地址空间中。 PCI 设备 11 并不能直接操作 0x10000000~0x1000FFFF 这段存储器域的地址空间,需要对 PCI 总线域的地址空间 0x90000000~0x9000FFFF 进行写操作,因为 PCI 总线地址空间 0x90000000~0x9000FFFF 已经被 HOST 主桥映射到 0x10000000~0x1000FFFF 这段存储器域。这个 DMA 写操作流程如下 (1)首先 PCI 设备 11 通过总线仲裁逻辑获得 PCI 总线 1 的使用权,之后将存储器写总线事务发送到 PCI 总线 1 上。值得注意的是,这个存储器写总线事务的目的地址是 PCI 总线域的地址空间 0x90000000~0x9000FFFF,这个地址是主存储器在 PCI 总线域的地址映射。(liyongjun疑问,HOST 主桥保存这份映射,而 PCI 设备 11 又是如何知道这个映射关系的呢?) 11: PCI 设备通过 DMA 向内存写数据时,PCI 设备发出的地址为 PCI 总线地址,我的问题是,PCI 设备如何知道 PCI 总线地址和内存总线地址的映射关系呢?我知道这个映射关系是存储在 HOST 主桥中的,PCI 设备是如何知道这个映射关系的呢? AI: PCI设备通过DMA向内存写数据时,需要知道PCI总线地址和内存总线地址的映射关系。这个映射关系存储在主机主桥中的PCI配置空间中的PCI Base Address Register(BAR)中。 主机主桥是PCI总线和系统总线(如PCIe或PCI-X)之间的桥接器。它负责管理PCI设备和系统总线之间的通信。当PCI设备插入主机时,主机主桥会为该设备分配一个唯一的PCI总线地址,并将该地址配置给设备。 PCI设备可以通过PCI配置空间访问该配置信息。PCI配置空间是一组寄存器,存储在设备的内存空间中。通过读取和写入这些寄存器,设备可以获取分配给它的PCI总线地址,并了解PCI总线地址和内存总线地址的映射关系。 设备可以使用PCI配置空间中的BAR寄存器来获取映射关系。每个BAR寄存器包含一个地址掩码和一个基地址。设备读取该寄存器,获得基地址并与地址掩码进行逻辑与运算,以获取映射到内存总线的地址范围。 通过BAR寄存器,设备可以确定映射关系,并使用正确的地址访问内存。这使得设备能够使用DMA直接向内存写入数据,而不需要主机的干预。 总结起来,PCI设备通过访问PCI配置空间中的BAR寄存器来获取PCI总线地址和内存总线地址的映射关系。这种映射关系由主机主桥进行配置,并通过BAR寄存器向设备公开。 11: 我知道的是 BAR 寄存器中保存 内存总线地址到 PCI 总线地址映射后的 PCI 总线基地址,难道还保存着 PCI 总线地址到内存总线地址映射后的 PCI 总线基地址? AI: 是的,您说得对。PCI设备通过BAR(Base Address Register)寄存器来了解PCI总线地址和内存总线地址的映射关系。每个PCI设备都有多个BAR寄存器,其中包含了PCI总线地址到内存总线地址的映射信息。 BAR寄存器中的值指示了PCI设备在PCI总线上的地址范围,并提供了与内存总线上对应地址的映射。PCI设备可以通过读取BAR寄存器中的值来获取PCI总线地址到内存总线地址的映射关系。 具体而言,当PCI设备需要向内存写入数据时,它会使用DMA(Direct Memory Access)进行传输。在进行DMA传输之前,PCI设备会读取相应的BAR寄存器来获取映射关系,从而知道应该将数据写入哪个内存地址。 因此,PCI设备通过读取BAR寄存器中的值来了解PCI总线地址到内存总线地址的映射关系,从而确定数据应该写入的内存地址。 (2)。。。 略 与 Cache 相关的 PCI 总线事务PCI 总线规范定义了一系列与 Cache 相关的总线事务,以提高 PCI 设备与主存储器进行数据交换的效率,即 DMA 读写效率。当 PCI 设备使用 DMA 方式向存储器进行读写操作时,一定需要经过 HOST 主桥,而 HOST 主桥通过 FSB 总线向存储器控制器进行读写操作时,需要进行 Cache 共享一致性操作。 PowerPC 处理器,如 MPC8548 处理器,可以使用 Inbound 寄存器的 RTT 字段和 WTT 字段,设置在 PCI 设备进行 DMA 操作时,是否需要进行 Cache 一致性操作,是否可以将数据直接写入 Cache 中。 HOST 主桥 PIWARn 寄存器中有 RTT 字段和 WTT 字段,在 Inbound 窗口中可以规定 PCI 设备访问主存储器时,是否需要进行 Cache 一致性操作(Cache Lock and Allocate),在进行 DMA 写操作时,数据是否可以直接进入 Cache。该字段是 PowerPC 处理器对 PCI 总线规范的有效补充,由于该字段的存在,PowerPC 处理器的 PCI 设备可以将数据直接写入 Cache,也可以视情况决定 DMA 操作是否需要进行 Cache 共享一致性操作。 Cache 一致性的基本概念PCI 设备对可 Cache 的存储器空间进行 DMA 读写操作的过程较为复杂,本节仅介绍在 Cache Memory 系统中与 PCI 设备进行 DMA 操作相关的一些最为基础的概念。 Cache 一致性协议 多数 SMP 处理器系统使用 MESI 协议处理多个处理器之间的 Cache 一致性。该协议也称为 Illinois protocol,在 SMP 处理器系统中得到广泛应用。MESI 协议使用四个状态位描述每一个 Cache 行。 M(Modified)位。M 位为 1 时表示当前 Cache 行中包含的数据与存储器中的数据不一致,而且它仅在本 CPU 的 Cache 中有效,不在其它 CPU 的 Cache 中存在副本,在这个 Cache 行中的数据是当前处理器系统中最新的数据副本。当 CPU 对这个 Cache 行进行替换操作时,必然会引发系统总线的写周期,将 Cache 行中数据与内存中的数据进行同步。E(Exclusive)位。E 位为 1 时表示当前 Cache 行中包含的数据有效,而且该数据仅在当前 CPU 的 Cache 中有效,而不在其它 CPU 的 Cache 中存在副本。在该 Cache 行中的数据是当前处理器系统中最新的数据副本,而且与存储器中的数据一致。S(Shared)位。S 位为 1 表示 Cache 行中包含的数据有效,而且在当前 CPU 和至少其它一个 CPU 中具有副本。在该 Cache 行中的数据是当前处理器系统中最新的数据副本,而且与存储器中的数据一致。I(Invalid)位。I 位为 1 表示当前 Cache 行中没有有效数据或者该 Cache 行没有使能。MESI 协议在进行 Cache 行替换时,优先使用 I 位为 1 的 Cache 行。在一个处理器系统中,主设备(CPU 或者外部设备)进行存储器访问时,将试图从存储器系统(主存储器或者其它 CPU 的 Cache)中获得最新的数据副本。如果该主设备访问的数据没有在本地命中时,将从其它 CPU 的 Cache 中获得数据,如果这些数据仍然没有在其它 CPU 的 Cache 中命中,主存储器将提供数据。外设设备进行存储器访问时,也需要进行 Cache 共享一致性。 在 MOESI (MESI 的变种)模型中,“Probe Read”表示主设备从其它 CPU 中获取数据的目的是为了读取数据;而“Probe Write”表示主设备从其它 CPU 中获取数据副本的目的是为了写入数据;“Read Hit”和“Write Hit”表示主设备在本地 Cache 中获得数据副本;“Read Miss”和“Write Miss”表示主设备没有在本地 Cache 中获得数据副本;“Probe Read Hit”和“Probe Write Hit”表示主设备在其它 CPU 的 Cache 中获得数据副本。 本节为简便起见,仅介绍 CPU 进行存储器写和与 O 状态相关的 Cache 行状态迁移。 当 CPU 对一段存储器进行写操作时,如果这些数据在本地 Cache 中命中时,其状态可能为 E、S、M 或者 O。 状态为 E 或者 M 时,数据将直接写入到 Cache 中,并将状态改为 M。状态为 S 时,数据将直接写入到 Cache 中,并将状态改为 M,同时其它 CPU 保存该数据副本的 Cache 行状态将从 S 或者 O 迁移到 I(Probe Write Hit)。状态为 O 时,数据将直接写入到 Cache 中,并将状态改为 M,同时其它 CPU 保存该数据副本的 Cache 行状态将从 S 迁移到 I(Probe Write Hit)。当 CPU A 对一段存储器进行写操作时,如果这些数据没有在本地 Cache 中命中,而在其它 CPU,如 CPU B 的 Cache 中命中时,其状态可能为 E、S、M 或者 O。其中 CPU A 使用 CPU B 在同意 Cache 共享域中。 Cache 行状态为 E 时,CPU B 将该 Cache 行状态改为 I;而 CPU A 将从本地申请一个新的 Cache 行,将数据写入,并该 Cache 行状态更新为 M。Cache 行状态为 S 时,CPU B 将该 Cache 行状态改为 I,而且具有同样副本的其他 CPU 的 Cache 行也需要将状态改为 I;而 CPU A 将从本地申请一个 Cache 行,将数据写入,并该 Cache 行状态更新为 M。Cache 行状态为 M 时,CPU B 将原 Cache 行中的数据回写到主存储器,并将该 Cache 行状态改为 I,具有同样数据副本的其他 CPU 的 Cache 行也需要将状态从 S 更改为 I;CPU A 将从本地申请一个 Cache 行,将数据写入,并该 Cache 行状态更新为 M。 Cache 行状态可以从 M 迁移到 O。例如当 CPU A 读取的数据从 CPU B 中命中时,如果在 CPU B 中 Cache 行的状态为 M 时,将迁移到 O,同时 CPU B 将数据传送给 CPU A 新申请的 Cache 行中,而且 CPU A 的 Cache 行状态将被更改为 S。 HIT# 和 HITM# 信号 在 SMP 处理器系统中,每一个 CPU 都使用 HIT# 和 HITM# 信号反映 HOST 主桥访问的地址是否在各自的 Cache 中命中。当 HOST 主桥访问存储器时,CPU 将驱动 HIT# 和 HITM# 信号,其描述如下![]() 如果访问的数据在 Cache 中命中,CPU 会通知 FSB 总线,PCI 设备所访问的数据在 Cache 中。 如果 Cache 行的状态为 E,Response Agent 将提供数据,而 CPU 不必改变 Cache 行状态。Snoopy Agent 可以直接将数据提供给 HOST 主桥,无疑数据访问的延时更短。 PCI 设备进行 DMA 写时发生 Cache 命中,如果命中的 Cache 行状态为 E,PCI 设备(通过 HOST 主桥)写入存储器的信息比 Cache 行中的数据新,而且 PCI 设备在进行 DMA 写操作之前,存储器域 Cache 中数据一致,此时 CPU 进需要在 Snoop Phase 使无效(Invalidate)这个 Cache 行,然后 FSB 总线事务将数据写入存储器即可。当然如果 FSB 总线事务可以将数据直接写入 Cache,并将 Cache 行的状态更改为 M,也可以提高 DMA 写的效率。 预读机制无论 Cache 的命中率有多高,总有发生 Cache 行 Miss 的情况,使用预读机制可以在一定程度上降低 Cache 行失效带来的影响。 预读机制包括指令预读、数据预读、外部设备的预读队列和操作系统提供的预读策略(prefetch函数?)。 指令预读指令预读是指在 CPU 执行某段程序时,根据程序的执行情况,提前将指令从主存储器预读到指令 Cache 中,从而当 CPU 需要执行这段程序时,不需要从主存储器,而是从指令 Cache 中获取指令,从而极大缩短了 CPU 获取指令的延时。 在一段程序中,存在大量的分支预测指令,因而在某种程度上增加了指令预读的难度。 数据预读数据预读是指在处理器进行运算时,提前通知存储器系统将运算过程中需要的数据准备好,而当处理器需要这些数据时,可以直接从 Cache 中获得这些数据。 但是在某些特殊情况下,采用预读机制有可能会降低效率。首先在一个较为复杂的应用中,很有可能预读的数据没有被充分利用,一个程序可能会按照不同的分支执行,而执行每一个分支所使用的数据并不相同。其次预读的数据即使是有效的,这些预读的数据也可能会污染整个 Cache 资源,在大规模并行任务的执行过程中,有可能引发 Cache 颠簸,从而极大地降低系统效率。 处理器提供了软件预读和硬件预读两种方式。 软件预读 软件预读指令都有一个共同的特点,就是在处理器真正需要数据之前,向存储器发出预读请求,这个预读请求不需要等待数据真正到达存储器之后,就可以执行完毕(预读指令在一个时钟周期内就可以执行完毕)。从而处理器可以继续执行其它指令,以实现存储器访问与处理器运算同步进行,从而提高了程序的整体执行效率。 在一个处理器系统中,预读的目标设备并不仅限于存储器,程序员还可以根据实际需要对外部设备进行预读。但并不是所有的外部设备都支持预读,只有“well-behavior”存储器支持预读。处理器使用的内部存储器,如基于 SDRAM、DDR-SDRAM 或者 SRAM 的主存储器是“well-behavior” 存储器,有些外部设备也是“well-behavior” 存储器。这些“well-behavior” 存储器具有以下特点。 (1)对这些存储器设备进行读操作时不会改变存储器的内容。显然主存储器具有这种性质。如果一个主存储器的一个数据为 0,那么读取这个数据 100 次也不会将这个结果变为 1。但是在外部设备中,一些使用存储器映像寻址的寄存器具有读清除的功能。比如某些中断状态寄存器。当设备含有未处理的中断请求时,该寄存器的中断状态为 1,对此寄存器进行读操作时,硬件将自动地把该中断位清零。 (2)对“well-behavior” 存储器的多次读操作,可以合并为一次读操作。如向这个设备的地址 n、n + 4、n + 8、n + 12 地址处进行四个双字的读操作,可以合并为对 n 地址的一次突发读操作(大小为 4 个双字)。 PCIe 细节PCIe 总线由若干层次组成,包括事务层、数据链路层和物理层。 PCIe 总线使用数据报文进行数据传递,这些数据报文需要通过 PCIe 总线的这些层次。PCIe 总线的这种数据传递方式与互联网使用 TCP/IP 协议进行数据传递有类似之处。 实际上,在互联网中存在的许多概念也存在于 PCIe 总线中,如交换、路由和仲裁机制等,不过两者实现上的最大不同在于前者主要使用软件程序实现其协议栈,而后者使用硬件逻辑实现。 半导体工艺的逐步提高,使得更多的软件算法可以使用硬件逻辑来实现,这给从事集成电路设计的工程师带来了巨大的挑战,因为他们使用 Verilog/VHDL 程序编写的算法,之前是使用 C 或 C++ 这样的高级语言实现的。 (C:send_byte(data), VHDL: clk、data) PCIe 总线在系统软件级与 PCI 总线兼容,基于 PCI 总线的系统软件几乎可以不经修改直接移植到 PCIe 总线中。绝大多数 PCI/PCI-X 总线使用的总线事务都被 PCIe 总线保留,而 PCI 设备使用的配置空间也被 PCIe 总线继承。基于 PCI 体系结构的系统编程模型,几乎可以在没有本质变化的前提下,直接在 PCIe 体系结构中使用。 但是从体系系统的角度上看,PCIe 总线还是增加了一些新的特性,其中一些特性不仅是称呼上的变化,而且在功能上也得到了增强。如在 PCIe 体系结构中出现的 RC(Root Complex)。RC 的主要功能与 PCI 总线中的 HOST 主桥类似,但是在 HOST 主桥的基础上增加了许多功能。 在不同处理器系统中,RC 的实现方式不同,因此仅仅用 PCIe 总线控制器来称呼 RC 是不够的,实际上 PCIe 总线规范对 RC 并没有一个合适的解释。Intel 并没有使用 PCIe 总线控制器,而是使用 RC 管理 PCIe 总线。在 x86 处理器体系结构中,RC 并不仅仅管理 PCIe 设备的数据访问,而且还包含访问控制、错误处理和虚拟化技术等一系列内容。因此用 PCIe 总线控制器统称 RC,在 x86 处理器体系结构中并不合适。 虽然从系统软件的角度来看,PCI 总线与 PCIe 总线基本一致。但是从硬件设计的角度来看 PCIe 总线完全不同于 PCI 总线,基于 PCIe 总线各类设备的硬件设计难度远大于基于 PCI 总线的对应设备的设计难度。 PCI 总线使用并行总线结构,在同一条总线上的所有外部设备共享总线带宽,而 PCIe 总线使用了高速差分总线,并采用端到端的连接方式,因此在每一条 PCIe 链路中只能连接两个设备。这使得 PCIe 与 PCI 总线采用的拓扑结构有所不同。PCIe 总线除了在连接方式上与 PCI 总线不同之外,还使用了一些在网络通信中使用的技术,如支持多种数据路由方式,基于多通路的数据传递方式,基于报文的数据传送方式,并充分考虑了在数据传送中出现的服务质量QoS(Quality of Service)问题。 PCIe 总线的基础知识PCIe 总线使用端到端的连接方式,在一条 PCIe 链路的两端只能各连接一个设备,这两个设备互为数据发送端和数据接收端。PCIe 总线除了总线链路外,还具有多个层次,发送端发送数据时将通过这些层次,而接收端接收数据时也使用这些层次。PCIe 总线使用的层次结构与网络协议栈较为类似。 PCIe 总线相当于网线,相当于物理层之下的第 0 层。 端到端的数据传递PCIe 链路使用“端到端的数据传送方式”,发送端和接收端中都含有 TX(发送逻辑)和 RX(接收逻辑),其结构图如下 PCIe传输速率和有效带宽计算方式: PCIe是串行总线,PCIe1.0的线上比特传输速率为2.5Gb/s,物理层使用8/10编码,即8比特的数据,实际在物理线路上是需要传输10比特的,因此: PCIe1.0 x 1的带宽=(2.5Gb/s )/ 10bit =250MB/s 这是单条Lane的带宽,有几条Lane,那么整个带宽就是250MB乘以Lane的数目。 PCIe2.0的线上比特传输速率在PCIe1.0的基础上翻了一倍,为5Gb/s,物理层同样使用8/10编码,所以: PCIe2.0 x 1的带宽=(5Gb/s )/ 10bit = 500MB/s 同样,有多少条Lane,带宽就是500MB/s乘以Lane的数目。 PCIe3.0的线上比特传输速率没有在PCIe2.0的基础上翻倍,不是10Gb/s,而是8Gb/s,但物理层使用的是128/130编码进行数据传输,所以: PCIe3.0 x 1的带宽=(8Gb/s)/ 8bit = 1GB/s 同样,有多少条Lane,带宽就是1GB/s乘以Lane的数目。 由于采用了128/130编码,128比特的数据,只额外增加了2bit的开销,有效数据传输比率增大,虽然线上比特传输率没有翻倍,但有效数据带宽还是在PCIe2.0的基础上做到翻倍。 这里值得一提的是,上面算出的数据带宽已经考虑到8/10或者128/130编码,因此,大家在算带宽的时候,没有必要再考虑线上编码的问题了。 —— https://www.elecfans.com/d/2208020.html PCIe 链路使用串行方式进行数据传送,然而在芯片内部,数据总线仍然是并行的,因此 PCIe 链路接口需要进行串并转换,这种串并转换将产生较大的延时。除此之外 PCIe 总线的数据报文需要经过事务层、链路层、物理层,这些数据报文在穿越这些层次时,也将带来延时。 在基于 PCIe 总线的设备中,x1 的 PCIe 链路最为常见。 PCIe 总线物理链路间的数据传递使用基于时钟的同步传送机制,但是在物理链路上并没有时钟线,PCIe 总线的接收端含有时钟恢复模块 CDR(Clock Data Recovery),CDR 将从接收报文中提取接收时钟,从而进行同步数据传递,PCIe 设备进行链路训练时将完成时钟的提取工作。 物理层发送数据所依据的 Tx 时钟必须随数据发送到接收方,以便接收方以此时钟为基准接收数据。但是,物理层并不将 Tx 时钟本身发送到传输线上(没有专门的时钟线),而是将之融入物理包的位流中,由接收方借助本地的锁相环(PLL)电路从接收位流中还原出这个时钟,作为数据接收时钟。 为此发送逻辑设置 8/10b 编码器,将乱序后的每个 8 位字符编码为 10 位,称为符号,也称为符号字节(Sbyte),目的是保证位流中 1 到 0 和 0 到 1 的跳变沿有足够的密度,使接收方 PLL 电路能够从接收位流中抽取出时钟。 由于将每个字节扩展为 10 位符号,在传输性能上会损失 25%。 10 位符号由并-串转换器转换为串行位流,即在各通路上对包进行串行化。串行位流送到电气物理层的差分发送器,将包差分发送到通路上。 8b/10b 编码的主要目的是将串行数据的位发送时钟嵌入到串行位流中,在链路上省去随数据一起发送的时钟信号线,还避免了 2.5GHz 的高频时钟信号产生的 EMI 噪声(liyongjun疑问:采用差分信号不是可以减弱 EMI 吗)。另外,没有了时钟线,也就不需要考虑时钟线与通路信号线布线长度的匹配问题,使两端口之间链路的布线工作容易得多。 优越性具体包括: (1)嵌入时钟 (2)保证位流中不会含有多于 5 个的连续 1 或 0 (3)DC 平衡 (4)错误检测,即检查自链路初始化以来,被发送的 1 和 0 总数之间的差值是否接近 0 —— 《PCI、PCI-X 和 PCI Express 的原理及体系结构》 值得注意的是,在一个 PCIe 设备中除了需要从报文中提取时钟外,还使用了 REFCLK+ 和 REFCLK- 信号对作为本地参考时钟 PCIe 总线使用的信号PCIe 设备使用两种电源信号供电,分别是 Vcc 与 Vaux,其额定电压为 3.3V。其中 Vcc 为主电源,PCIe 设备使用的主要逻辑模块均使用 Vcc 供电,而一些与电源管理相关的逻辑使用 Vaux 供电。 PCIe 链路的最大宽度为 x32,但在实际应用中,x32 的链路宽度极少使用。一般提供 x16 的 PCIe 插槽,并使用 16 对 PETxx 信号用于发送链路,另外 16 对 PERxx 信号用于接收链路。除此之外,PCIe 总线还使用了下列辅助信号。 PERST# 信号 该信号为全局复位信号,由处理器系统提供,处理器系统需要为 PCIe 插槽和 PCIe 设备提供该复位信号。REFCLK+ 和 REFCLK- 信号 在一个处理器系统中,可能含有许多 PCIe 设备,这些设备可以作为 Add-In 卡与 PCIe 插槽连接,也可以作为内置模块,与处理器系统提供的 PCIe 链路直接相连,而不需要经过 PCIe 插槽。PCIe 设备与 PCIe 插槽都具有 REFCLK+ 和 REFCLK- 信号,其中 PCIe 插槽使用这组信号与处理器系统同步。 在一个处理器系统中,通常采用专用逻辑向 PCIe 插槽提供 REFCLK+ 和 REFCLK- 信号,如下图所示,其中 100MHz 的时钟源由晶振提供,并经过一个 “一推多” 的差分时钟驱动器生成多个同相位的时钟源,与 PCIe 插槽一一对应连接。![]() PCIe 总线采用串行连接方式,并使用数据包(Packet)进行数据传输,采用这种结构有效去除了在 PCI 总线中存在的一些边带信号,如 INTx 和 PME# 等信号。 在 PCIe 总线中,数据报文在接收和发送过程中,需要通过多个层次,包括事务层、数据链路层和物理层。PCIe 总线的层次结构如下图所示 PCIe 链路使用端到端的数据传送方式。在一条 PCIe 链路中,这两个端口是完全对等的,而且一个 PCIe 链路的一端只能连接一个设备。因此 PCIe 链路必须使用 Switch 扩展 PCIe 链路后,才能连接多个设备。使用 Switch 进行链路扩展的实例如下图所示 PCIe 总线作为处理器系统的局部总线,主要目的是连接外部设备。使用 RC、Switch、PCIe-toPCI 桥这些基本模块连接 PCIe 和 PCI 设备。 在 PCIe 总线中,基于 PCIe 总线的设备,也称为 EP(EndPoint)。 在不同的处理器系统中,RC 的实现有较大差异。PCIe 总线规范并没有规定 RC 的实现细则。在有些处理器系统中,RC 相当于 PCIe 主桥,也有的处理器系统也将 PCIe 主桥成为 PCIe 总线控制器。而在 x86 处理器系统中,RC 除了包含 PCIe 总线控制器之外,还包含一些其它组成部件。 如果一个 RC 中可以提供多个 PCIe 端口,这种 RC 也被称为多端口 RC。如 MPC8572 处理器的 RC 可以直接提供 3 条 PCIe 链路,因此可以直接连接 3 个 EP。 RC 是 PCIe 体系结构的一个重要组成部件,也是一个较为混乱的概念。在上图中,RC 包括存储器控制器、两个 FSB-to-PCIe 桥。 如果将 RC 中的其它功能忽略,RC 的主要功能与 PCI 总线中的 HOST 主桥类似,其主要作用是完成存储器域到 PCI 总线域的地址转换。 但是 RC 与 HOST 主桥并不相同,RC 除了完成地址空间的转换之外,还需要完成物理信号的转换。在 PowerPC 处理器的 RC 中,来自 OCeaN 或者 FSB 的信号协议与 PCIe 总线信号使用的电气特性并不兼容,使用的总线事务也并不相同,因此必须进行信号协议和总线事务的转换。 Switch从系统软件的角度上看,每一个 PCIe 链路都占用一个 PCI 总线号,但是一条 PCIe 链路只能连接一个 PCI 设备、Switch、EP 或者 PCIe 桥片。 一个 PCIe 链路需要挂接多个 EP 时,需要使用 Switch 进行链路扩展。 在 PCIe 体系结构中,Swicth 的设计难度仅次于 RC,Switch 也是 PCIe 体系结构的核心所在。从系统软件的角度上看,Switch 内部由多个 PCI-to-PCI 桥组成,其中每一个上游和下游端口都对应一个虚拟 PCI 桥。在一个 Switch 中,有多少个端口,在其内部就有多少个虚拟 PCI 桥,就有多少个 PCI 桥配置空间。值得注意的是,在 Switch 内部,还具有一条虚拟的 PCI 总线,用于连接各个虚拟 PCI 桥。系统软件在初始化 Switch 时,需要为这条虚拟 PCI 总线编号。 在 Switch 中存在多个端口,其中来自不同 Ingress 端口的报文可以发向同一个 Egress 端口,因此 Switch 必须要解决端口仲裁和路由选径的问题。所谓端口仲裁指来自不同 Ingress 端口的报文到达同一个 Egress 端口,报文的通过顺序。 PCI 设备使用基本配置空间,这个基本配置空间由 64 个字节组成,其地址范围为 0x00~0x3F,这 64 个字节是所有 PCI 设备必须支持的,事实上,许多 PCI 设备也仅支持这 64 个配置寄存器。 此外 PCI/PCI-X 和 PCIe 设备还扩展了 0x40~0xFF 这段配置空间,在这段空间主要存放一些与 MSI 或者 MSI-X 中断机制和电源管理相关的 Capability 结构。其中所有能够提交中断请求的 PCIe 设备,必须支持 MSI 或者 MSI-X Capability 结构。 PCIe 总线的事务层事务层是 PCIe 总线层次结构的最高层,该层次将接收 PCIe 设备核心层的数据请求,并将其转换为 PCIe 总线事务,PCIe 总线使用的这些总线事务在 TLP 头中定义。 PCIe 总线继承了 PCI/PCI-X 总线的大多数总线事务,如存储器读写、I/O 读写、配置读写总线事务,并增加了 Message 总线事务和原子操作等总线事务。 在 PCIe 总线中,不同的总线事务采用的路由方式不同。PCIe 总线继承了 PCI 总线的地址路由和 ID 路由方式,并添加了 “隐式路由” 方式。 PCIe 总线使用的数据报文首先在事务层中形成,这个数据报文也被称为事务层数据报文,即 TLP。TLP 在经过数据链路层时被加上 Sequence Number 前缀和 CRC 后缀,然后发向物理层。 TLP 格式
Fmt 和 Type 字段确认当前 TLP 使用的总线事务,TLP 头的大小是由 3 个双字还是 4 个双字组成,当前 TLP 是否包含有效负载。具体如下表 TLP 的路由是指 TLP 通过 Switch 或者 PCIe 桥片时采用哪条路径,最终到达 EP 或者 RC 的方法。 PCIe 总线一共定义了三种路由方法,分别是基于地址(Address)的路由,基于 ID 的路由和隐式路由(Implicit)方式。 存储器和 I/O 读写请求 TLP 使用基于地址的路由方式,这种方式使用 TLP 中的 Address 字段进行路由选径,最终到达目的地。 而配置读写报文、Cpl 和 CplD 报文使用基于 ID 的路由方式,这种方式使用 PCI 总线号进行路由选径。 而隐式路由方式主要用于 Message 报文的传递。在 PCIe 总线中定义了一系列消息报文,包括 “INTx Interrupt Signaling”、“Power Management Messages” 和 “Error Signal Messages” 等报文。隐式路由方式是指从下游端口到上游端口进行数据传递使用的路由方式,或用于 RC 向 EP 发出广播报文。 基于地址的路由在 PCIe 总线中,存储器读写和 I/O 读写 TLP 使用基于地址的路由方式。PCIe 设备使用的地址路由方式与 PCI 设备使用的地址路由方式类似(通过判断配置空间中能够接收的地址范围)。只是 PCIe 设备使用 TLP 进行数据传送,而 PCI 设备使用总线周期进行数据传送。 在 PCIe 总线中,基于ID 的路由方式主要用于配置读写请求 TLP、Cpl 和 CplD 报文。 (liyongjun:想想也是,读写配置空间,肯定使用 ID 路由方式比较好,因为 BAR 空间有可能还未初始化,想使用地址路由也无法使用) 基于 ID 路由的 TLP,使用 Bus Nuber、Device Number、Function Number 进行路由寻址。 隐式路由
如果 Switch 的上游端口接收了一条来自 RC 的广播消息,则将该报文发向所有的下游端口;如果 Switch 的下游端口接收了一条发向 RC 的消息报文时,Switch 将此报文直接转发到上游端口,直至 RC。 消息请求报文在 PCIe 总线中,多数消息报文使用隐式路由方式,其中 Byte 0 字段为通用 TLP 头,而 Byte 4 的第 3 字节中存放 Message Code 字段。 PCIe 总线规定了以下几类消息报文 INTx 中断消息报文(INTx Interrupt Signaling)电源管理消息报文错误消息报文锁定事务消息报文插槽电源限制消息报文Vendor-Defined Messages INTx 中断消息报文在 PCIe 总线中,PCIe 设备可以使用 legacy 中断方式提交中断请求,此时需要使用 INTx 中断消息报文向 RC 通知中断事件。 例如,在 PCIe 桥片上挂接的 PCI 设备可能并不支持 MSI 中断机制,因此需要使用 INTx 中断信号提交中断请求,此时 PCIe 桥需要将 INTx 信号转换为 INTx 中断消息报文(liyongjun:MT7916),并向 RC 提交中断请求。 在 PCIe 总线中,共有 8 种 INTx 中断消息报文 与事务层不同,数据链路层主要处理端到端的数据传送。在事务层中,源设备与目标设备间的传送距离较长,设备之间可能经过若干级 Switch;而在数据链路层中,源设备与目标设备在一条 PCIe 链路的两端(liyongjun:醍醐灌顶,类比于网络协议)(liyongjun:数据链路层,关键字:相邻)。 物理层是 PCIe 总线的最底层,也是 PCIe 总线体系结构的核心。在物理层中涉及许多与差分信号传递有关的模拟电路知识。 物理层简介物理层主要由物理层逻辑模块和物理层电气模块组成,逻辑模块包括 8/10b 编码、链路训练等一些基础的内容,物理层包括差分信号的处理。 物理层的电气模块与差分信号的工作原理密切相关,这部分原理包括一系列与信号完整性相关的课题,信号完整性所追求的目标如下 保证发送的信号可以被接收端正确接收保证发送的信号不会影响其它信号保证发送的信号不会损坏接收器件保证发送的信号不会产生较大的 EMI 电磁噪声。 PCIe 链路的差分信号所有信号的传递都需要一个电流回路,流入一个节点的电流总和等于流出这个节点的电流总和。单端信号使用地平面作为电流回路,而这个地平面并不是稳定的,极易收到干扰。减缓噪声的有效方法是为器件的电源提供退耦电容,在电路设计中,该方法极为普及。 即便如此,单端信号使用的地平面仍不足以信赖,仍会给单端信号的传递带来不小的干扰。 其次,单端信号容易受到其它信号的干扰,当单端信号频率较高时,信号在传递过程中衰减较大,而采用差分信号可以有效避免使用单端信号的这些问题。 差分信号对要求等长且平行走线,而且在实际的 PCB 中,最好做到同层等长,因为不同层间的特性阻抗并不完全相等,有一定误差。 PCIe 总线的链路训练与电源管理PCIe 总线进行链路训练时将初始化 PCIe 设备的物理层、发送接收模块和相关的链路状态信息,当链路训练成功结束后,PCIe 链路两端的设备可以进行正常的数据交换。 链路训练的过程由硬件逻辑完成,无需系统软件的参与。 PCIe 总线进行链路训练的主要目的是初始化 PCIe 链路的物理层、端口配置信息、相应的链路状态,并了解链路对端的拓扑结构,以便 PCIe 链路两端的设备进行数据通信。 一条 PCIe 总线提供的链路带宽可以是 x1、x2、x4、x8、x12 或者 x16,但是在这个 PCIe 链路上所挂接的 PCIe 设备并不会完全使用这些链路。如一个 x4 的 PCIe 设备可能会连接到 x16 的 PCIe 链路上。此时该 PCIe 设备在进行链路训练时,必须通知对端链路该设备实际使用的链路状态。 PCIe 链路两端的设备所使用的 Lane 可以错序连接,称之为 “Lane Reversal”。 并且,在相同的 Lane 上,差分信号的极性也可以错序连接,称之为 “Polarity Inversion” 流量控制(Flow Control)的概念起源于网络通信。 从数据传输的角度来看,整个网络中具有两类资源,一类是数据通路,另一类是数据缓冲。 在网络节点中含有缓冲区,暂存在这个节点中没有处理完毕的报文。 最初在网络设备中只为一条链路提供了一个缓冲区,如下图所示 假设报文 A 和 B 属于相同种类的报文,并且适用不同的 VC 传递,Node 4 已经阻塞了报文 A,阻塞报文 A 的原因在很大概率上也会对报文 B 适用。此时两个虚通路都被同一种类型的报文阻塞,其它报文将无法通过。因此在实际应用中,相同类型的数据报文多使用同一个 VC 进行数据传递。 目前多通路技术的应用已经普遍应用到网络传输中,虚通路是一种防止节点拥塞的有效方法。 流量控制的基本原理目前流量控制从理论到实现大多基于多通道技术。 流量控制的主要作用是在发送端和接收端进行数据传递时,合理地使用物理链路,避免因为接收端缓冲区容量不足而丢弃来自发送端的数据,从而要求发送端重新发送已经发送过的报文,并最终有效地利用网络带宽。 目前,几乎所有流量控制算法的核心都是根据接收端缓冲区的容量,向发送端提供反馈(liyongjun:TCP window size)。而发送端根据这个反馈,决定向接收端发送多少数据。这些流量控制算法都力求发送的每一个数据报文都能够被接收端正确接收,而不会被接收端因为缓冲不足而丢弃。 使用流量控制机制并不能提高网络的峰值带宽,相反还会降低网络的带宽,但是可以有效减少数据报文的重新发送,从而保证网络带宽被充分利用(liyongjun:例子:列车员、空姐)。
在 PCI 总线中,所有需要提交中断请求的设备,必须能够通过 INTx 引脚提交中断请求,而 MSI 机制是一个可选机制。 而在 PCIe 总线中,PCIe 设备必须支持 MSI 或者 MSI-X 中断请求机制,而可以不支持 INTx 中断消息。 在 PCIe 总线中,MSI 和 MSI-X 中断机制使用存储器写请求 TLP 向处理器提交中断请求。PCIe 设备在提交 MSI 中断请求时,都是向 MSI/MSI-X Capability 结构中的 Message Address 的地址写 Message Data 数据,从而组成一个存储器写 TLP,向处理器提交中断请求。 有些 PCIe 设备还可以支持 Legacy 中断方式(通过发送 Assert_INTx 和 Deassert_INTx 消息报文进行中断请求,即虚拟中断线方式)。主要原因是,在 PCIe 体系结构中,存在许多 PCI 设备,这些设备通过 PCIe 桥连接到 PCIe 总线中,这些 PCI 设备可能并不支持 MSI/MSI-X 中断机制,因此必须使用 INTx 信号进行中断请求。 MSI 中断机制最多只能支持 32 个中断请求,而且要求中断向量连续。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |