在学习和使用虚拟化技术的过程中,不免经常遇到与计算机底层硬件相关的知识,在X86中,基本都与PCIe相关。每次都只能避之不及,敬而远之。一次在无意中闯入了王齐老师的博客,看到《浅谈PCIe体系结构》系列文章,顿感天降甘霖,急我所需。拜读完该系列博文后,就买了王老师的《PCI Express体系结构导论》,全面学习下。书读的比较慢,有些章节并未细读,它让我理解了之前一直未想通的问题,学习许多想了解的底层知识,受益良多。
早期的计算机根据冯,诺依曼原理构建而成,由控制单元、计算单元、内存、IO设备组成,后来控制单元与计算单元结合形成了CPU,CPU与每个设备间都使用独立的一条总线(或许还不能称为总线,只是由多条电线连接)。随着早期小型机和微型机的发展,对计算机系统模块化要求的提高和降低成本,DEC提出memory-mapped I/O技术,使得CPU通过一个内存总线(memory bus)便可同时访问内存和IO设备,由此链接各个组件的总线结合而成,便有了系统总线(system bus),即最初的单总线结构。如下图所示:
图1 单总线结构
不过随着计算机的发展,这种单总线结构不能满足需求,被逐渐淘汰,目前只有一些嵌入式系统还在使用【2】。
现代的计算机系统一般由CPU、Cache、内存和多个输入输出设备(如硬盘、键盘、网卡等)组成,这些部件之间需要通过总线连接起来,以进行通信,组成一个完整的系统。但由于不同设备的数据传输速度存在差距,不能将快速设备和慢速设备通过系统总线直接相连,否则会由于快速设备需要等待慢速设备的响应,而浪费大量时间,影响系统处理能力。如CPU速度较快,而硬盘速度要慢得多,如果直接相连,在执行硬盘读写时,会由于硬盘反应较慢,导致CPU浪费大量时间在等待响应上,不能充分发挥其计算能力。因此计算机系统中,需要多种不同总线连接速度不同的设备,快速设备之间通过高速总线连接起来,慢速设备之间通过另一种总线连接,而快速设备与慢速设备之间通过控制器进行间接相连。这样快速设备可以尽情高速运行,而慢速设备也不用害怕影响系统整体性能,可以悠闲地慢慢响应了。于是便有了局部总线(local bus)和外围总线(peripheral bus)。
局部总线,是指集成在主板上,能够直接或几乎直接与CPU相连的总线,它的另一端可以接连设备,或者提供扩展槽。XT、ISA、EISA、VESA、PCI、PCIe等都属于局部总线。这类总线具有较大的总线带宽和较小的相应延时,用于连接CPU与高速设备,如:内存、显卡等。
外围总线,通过控制器与CPU间接相连,用于接入系统的外围设备,如:打印机、硬盘等。由于外围设备类型众多,外围总线种类也不少。有些外围总线可以连接一类外部设备,如通用串口总线(USB,2Universal Serial Bus);有些外围总线只能连接具体的设备,如SATA\ISCI。
图 2 面向内存的双总线结构
在1990中后期,Intel公司在局部总线和外围总线的基础上,又扩展出了后端总线(BEB,back-side bus)和前端总线(FSB,front-side bus),前端总线有时也被人们称为系统总线,但与最初的系统总线已不相同了。近期又推出更新的总线技术,如HyperTransport和Intel QuickPath Interconnect。不过这里就暂时忽略,请查看参考文献【1】。
PCI总线
PCI(Peripheral Component Interconnect)总线规范由Intel的IAL(Intel Architecture Lab)于1992提出,它的诞生与计算机的密切发展相关。CPU主频的不断提升,导致计算机系统需要速度更快、带宽更高的局部总线,PCI总线由此应运而生。它推出之后,很快得到了主流产商的认同,替代了当时并存的多种局部总线(EISA、VESA)。与之前的局部总线相比,它具有以下优点:
- PCI总线域空间与存储域空间隔离。每一个PCI总线树都具有独立的地址空间,挂接在总线树上的PCI设备地址不会受到存储域地址空间和其它总线域地址空间划分的影响,实现与其它地址空间解耦的,达到PCI设备灵活配置的目的。
- 可扩展性,每一条PCI总线都可挂接多个PCI设备,并且可以通过PCI桥扩展出另外一条新的PCI总线,具有良好的扩展性。一个PCI总线树上,最多可以挂接256个PCI设备(包括PCI桥)。
- 动态配置机制。PCI设备使用的地址可以根据需要有系统软件动态分配。使用这种方式合理地解决了设备间的地址冲突问题,从而实现了‘即插即用’功能。因此PCI总线不需要使用ISA或EISA接口卡为解决地址冲突而使用的硬件跳线。
- 总线带宽。与之前的局部总线相比,极大提高了数据传送带宽。32位/33MHz的PCI总线可提供132MB/s的峰值带宽,而64位/66MHz的PCI总线可以提供的峰值带宽为532MB/s。而ISA总线的最高主频为8MHz,位宽为16,其峰值带宽为16MB/s/EISA总线的最高主频为8.33MHz,位宽为32,其峰值带宽为33MB/s。而MCA总线的最高主频为10MHz,位宽为32,其峰值带宽为40MB/s。
- 共享总线机制。PCI设备通过仲裁获得PCI总线的使用权后,才能进行数据传输。因此PCI设备在PCI总线上传输数据并不需要处理器的干预,减小其压力。
- 中断机制。PCI总线上的设备可以通过四根中断请求信号INTA~D#向处理器提交中断请求。与ISA总线上的设备不同,PCI设备可以共享这些中断请求信号,不同的PCI设备可以将这些中断请求信号线与后,与中断控制器的中断请求引脚连接。PCI总线还进一步提出了MSI(Message Signal Interrupt)机制,该机制使用存储器写总线事务传递中断请求,并可一使用X86处理器的FSB总线提供的Interrupt Message总线事务,从而提高了PCI设备的中断请求效率。
图3 PCI总线树
如图3所示,PCI体系结构由HOST主桥、PCI总线、PCI桥和PCI设备等模块组成。最上层PCI总线由HOST主桥,并由PCI桥扩展出多条PCI总线,形成一个倒树形结构的PCI总线树。HOST主桥负责存储域地址空间与PCI域地址空间的相互翻译和CPU读写指令与PCI总线事务间的转换。由于HOST主桥与主存储器控制器在同一级总线(即前端总线FSB)上,因此PCI设备可以方便地通过HOST主桥访问主存储器,即DMA操作。PCI总线还可以通过PCI-ISCI桥、PCI-USB桥、PCI-ISA桥扩展出其它的总线,以连接支持这些接口的外围设备。
PCI总线是并行总线,由挂接在该总线上的多个PCI设备共享。它由32位A/D信号(数据/地址信号)、控制信号、仲裁信号、中断信号等组成。地址总线和数据总线共享这32位A/D信号,分时复用。在地址周期传输地址信号,寻址特定的PCI设备。特确定目标后,数据周期随后传输数据信号,完成读写任务。
图4 DFS算法初始化PCI总线
对PCI总线树进行初始化时,系统软件采用DFS算法对PCI总线进行遍历。DFS是搜索算法的一种,其实现机制是沿着一个树的深度遍历各个节点,并尽可能深地搜索树的分支,DFS算法为线性时间复杂度,适合对拓扑结构未知的PCI总线树进行遍历。如图4所示,系统软件首先指定与HOST主桥相连的PCI总线为BUS 0,其次搜索Bus0上的PCI桥,忽略PCI设备,因为PCI设备不能扩展新的PCI总线。找到第一个PCI桥Bridge 1,将Bridge 1的下游PCI总线设为BUS 1。接着再查找BUS 1的PCI桥,发现Bridge 2,并将Bridge 2的下游PCI总线设为BUS 2。继续搜索BUS 2上的PCI桥,发现Bridge 4,将Bridge 4 下游总线设为BUS 3。继续搜索BUS 3,由于BUS 3没有连接PCI桥,则返回BUS 2继续搜索,由于BUS 2唯一的bridge 4已经搜索过,则继续返回BUS 1。发现Bridge 3,并将Bridge 3的下游总线设为BUS 4。到此,PCI总线号的初始化基本完成。对于一个总线号的设置是通过对该总线连接PCI桥的配置空间进行设置的,在初始化完成后,PCI桥配置空间中的Primary Bus Number\Secondary Bus Number和Subordinate Bus Number寄存器中分别保存了:该PCI桥的上游总线号,下游总线号和以该PCI桥为根的PCI总线子树的最大总线号。
PCIe总线
随着CPU的不断发展,PCI总线的最高峰值带宽已不能满足需求。PCI总线采用单端并行信号进行数据传输,由于单端信号容易被外部干扰,其总线频率很难进一步提高。如果采用提高总线位宽来提高其传输带宽,在性价比上,又不是最优。而且PCI总线在设计上没有考虑到带宽、流量控制和数据传输质量等问题,所以PCI总线不能满足现代处理器的需要。
PCIe总线由此诞生,它是基于PCI总线发展的新一代局部总线,可以有效解决PCI总线存在的一些问题。首先,PCIe总线可以提高更大的总线带宽,PCIe V3.0支持的最高总线频率为4GHz,远高于PCI总线的最高频率。其次PCIe总线支持虚拟通路(Virtual Channel)技术,优先级不同的数据报文可以使用不同的虚拟通路,而每一条虚拟通路可以独立设置缓冲,从而相对合理的解决了数据传输过程中的服务质量问题。
PCIe总线在设计上采用分层结构,由事务层、链路层、物理层三部分组成,使用数据报文进行数据传递,这些报文需要依次通过PCIe总线的这些层次。这种结构与TCP/IP协议有点类似,不过前者是从硬件上实现的。事务层、链路层、物理层分别从不同方面对PCI总线进行改进和功能扩展。
- 事务层:PCIe总线的事务类型继承了PCI总线的,并进行了扩展。事务类型在事务层形成,通过TLP(Transaction Layer Packet)表示。在TLP中有一个字节(8位)用于表示事务类型,最大理论事务数可达256,远大于PCI总线通过C/BE四位信号识别的、最多为16的事务数。事务层接收来自PCIe设备核心层的数据,将其封装为TLP后,发向链路层。并接收来自链路层的数据,发向设备核心。PCIe使用split方式处理所有Non-Posted总线事务,使得发送端在发送完事务请求后,可以立即释放总线。事务层还可以通过设置TLP的VC字段,支持流量控制和虚拟通路管理等一系列特性。
- 链路层:链路层的主要功能是保证来自事务层的TLP在PCIe链路中的正确传递。链路层接收来自事务层的TLP,并加上相应的数据头和数据尾封装成DLLP(Data Link Layer Packet),然后发向物理层。并接收来自物理层的DLLP,将其解析成TLP发向事务层。为保证PCIe链路的正常工作,链路层本身也定义了一系列DLLP,这类DLLP产生于链路层,也消费于链路层,事务层不会看到。与PCI总线不同,PCIe总线采用了端到端的连接方式,一条PCIe链路的两端只能各连一个设备,所以可以使用ACK/NAK协议发送和接收TLP,保证数据传递的完整性和一致性。
- 物理层:PCIe在物理层使用了高速差分总线,替代了PCI总线的并行总线结构。高速差分总线的采用极大地提高了PCIe总线频率,从而提供更高的数据带宽。与并行总线相比,它还具有抗干扰能力强、逻辑状态定位准等优点。不过由于差分总线在布线时,要求等长、等宽、同板面,比并行总线要求更严格,带来一定的难度。由于数据经过PCIe总线时都需要通过三层结构,而且数据通过PCIe总线传输和接收时需要分别进行并串和串并转换,这使得数据经过PCIe总线传输时会有相对较大的延时。
在硬件设计上,PCIe总线做了巨大的改变,基本看不到PCI总线的影子。不过由于PCIe总线事务继承于PCI总线,都支持配置空间读写事务、存储空间读写事务、IO空间读写事务,所以在软件层面上看,它们基本兼容,PCI总线的系统软件基本可以不加修改的用于PCIe总线。
参考文献
【1】http://en.wikipedia.org/wiki/Front-side_bus
【2】http://en.wikipedia.org/wiki/System_bus
【3】http://en.wikipedia.org/wiki/Peripheral_bus
【4】http://www.science.unitn.it/~fiorella/guidelinux/tlk/node76.html
转载请注明出处 blog.csdn.net/xuriwuyun