一、PCIe匯流排的事務層

事務層是PCIe匯流排層次結構的最高層,該層次將接收PCIe裝置核心層的資料請求,並將其轉換為PCIe匯流排事務,PCIe匯流排使用的這些匯流排事務在TLP頭中定義。PCIe匯流排繼承了PCI/PCI-X匯流排的大多數匯流排事務,如儲存器讀寫、I/O讀寫、配置讀寫匯流排事務,並增加了Message匯流排事務和原子操作等匯流排事務。

本節重點介紹與資料傳送密切相關的匯流排事務,如儲存器、I/O、配置讀寫匯流排事務。在PCIe匯流排中,Non-Posted匯流排事務分兩部分進行,首先是傳送端向接收端提交匯流排讀寫請求,之後接收端再向傳送端傳送完成(Completion)報文。PCIe匯流排使用Split傳送方式處理所有Non-Posted匯流排事務,儲存器讀、I/O讀寫和配置讀寫這些Non-Posted匯流排事務都使用Split傳送方式。PCIe的事務層還支援流量控制和虛通路管理等一系列特性,而PCI匯流排並不支援這些新的特性。

在PCIe匯流排中,不同的匯流排事務採用的路由方式不相同。PCIe匯流排繼承了PCI匯流排的地址路由和ID路由方式,並添加了“隱式路由”方式。

PCIe匯流排使用的資料報文首先在事務層中形成,這個資料報文也被稱之為事務層資料報文,即TLP,TLP在經過資料鏈路層時被加上Sequence Number字首和CRC字尾,然後發向物理層。

資料鏈路層還可以產生DLLP(Data Link Layer Packet)。DLLP和TLP沒有直接關係,DLLP是產生於資料鏈路層,終止於資料鏈路層,並不會傳遞到事務層。DLLP不是TLP加上字首和字尾形成的。資料鏈路層的報文DLLP通過物理層時,需要經過8/10b編碼,然後再進行傳送。資料的接收過程是傳送過程的逆過程,但是在具體實現上,接收過程與傳送過程並不完全相同。


1、TLP的格式


當處理器或者其他PCIe裝置訪問PCIe裝置時,所傳送的資料報文首先通過事務層被封裝為一個或者多個TLP,之後才能通過PCIe匯流排的各個層次傳送出去。TLP的基本格式如圖5 1所示。

一個完整的TLP由1個或者多個TLP Prefix、TLP頭、Data Payload(資料有效負載)和TLP Digest組成。TLP頭是TLP最重要的標誌,不同的TLP其頭的定義並不相同。TLP頭包含了當前TLP的匯流排事務型別、路由資訊等一系列資訊。在一個TLP中,Data Payload的長度可變,最小為0,最大為1024DW。

TLP Digest是一個可選項, 一個TLP是否需要TLP Digest由TLP頭決定。Data Payload也是一個可選項,有些TLP並不需要Data Payload,如儲存器讀請求、配置和I/O寫完成TLP並不需要Data Payload。

TLP Prefix由PCIe V2.1匯流排規範引入,分為Local TLP Prefix和EP-EP TLP Prefix兩類。其中Local TLP Prefix的主要作用是在PCIe鏈路的兩端傳遞訊息,而EP-EP TLP Prefix的主要作用是在傳送裝置和接收裝置之間傳遞訊息。設定TLP Prefix的主要目的是為了擴充套件TLP頭,並以此支援PCIe V2.1規範的一些新的功能。

TLP頭由3個或者4個雙字(DW)組成。其中第一個雙字中儲存通用TLP頭,其他欄位與通用TLP頭的Type欄位相關。一個通用TLP頭由Fmt、Type、TC、Length等欄位組成,如圖5 2所示。

如果儲存器讀寫TLP支援64位地址模式時,TLP頭的長度為4DW,否則為3DW。而完成報文的TLP頭不含有地址資訊,使用的TLP頭長度為3DW。其中Byte 4~Byte 15的格式與TLP相關,下文將結合具體的TLP介紹這些欄位。

1.1、通用TLP頭的Fmt欄位和Type欄位

Fmt和Type欄位確認當前TLP使用的匯流排事務,TLP頭的大小是由3個雙字還是4個雙字組成,當前TLP是否包含有效負載。其具體含義如表5 1所示。

表5 1 Fmt[1:0]欄位

Fmt[2:0] TLP的格式
0b000 TLP大小為3個雙字,不帶資料。
0b001 TLP大小為4個雙字,不帶資料。
0b010 TLP大小為3個雙字,帶資料。
0b011 TLP大小為4個雙字,帶資料。
0b100 TLP Prefix
其他 PCIe匯流排保留

其中所有讀請求TLP都不帶資料,而寫請求TLP帶資料,而其他TLP可能帶資料也可能不帶資料,如完成報文可能含有資料,也可能僅含有完成標誌而並不攜帶資料。在TLP的Type欄位中存放TLP的型別,即PCIe匯流排支援的匯流排事務。該欄位共由5位組成,其含義如表5 2所示。

表5 2 Type[4:0]欄位

TLP型別 Fmt[2:0] Type[4:0] 描述
MRd 0b000、0b001 0b0 0000 儲存器讀請求;TLP頭大小為3個或者4個雙字,不帶資料。
MRdLk 0b000、0b001 0b0 0001 帶鎖的儲存器讀請求;TLP頭大小為3個或者4個雙字,不帶資料。
MWr 0b010、0b011 0b0 0000 儲存器寫請求;TLP頭大小為3個或者4個雙字,帶資料。
IORd 0b000 0b0 0010 IO讀請求;TLP頭大小為3個雙字,不帶資料。
IOWr 0b010 0b0 0010 IO寫請求;TLP頭大小為3個雙字,帶資料。
CfgRd0 0b000 0b0 0100 配置0讀請求;TLP頭大小為3個雙字,不帶資料。
CfgWr0 0b010 0b0 0100 配置0寫請求;TLP頭大小為3個雙字,帶資料。
CfgRd1 0b000 0b0 0101 配置1讀請求;不帶資料。
CfgWr1 0b010 0b0 0101 配置1寫請求;帶資料。
TCfgRd 0b010 0b1 1011 本書對這兩種匯流排事務不做介紹。
TCfgWr 0b001 0b1 1011  
Msg 0b001 0b1 0r2r1r0 訊息請求;TLP頭大小為4個雙字,不帶資料。“rrr”欄位是訊息請求報文的Route欄位,下文將詳細介紹該欄位。
MsgD 0b011 0b1 0r2r1r0 訊息請求;TLP頭大小為4個雙字,帶資料。
Cpl 0b000 0b0 1010 完成報文;TLP頭大小為3個雙字,不帶資料。包括儲存器、配置和I/O寫完成。
CplD 0b010 0b0 1010 帶資料的完成報文,TLP頭大小為3個雙字,包括儲存器讀、I/O讀、配置讀和原子操作讀完成。
CplLk 0b000 0b0 1011 鎖定的完成報文,TLP頭大小為3個雙字,不帶資料。
CplDLk 0b010 0b0 1011 帶資料的鎖定完成報文,TLP頭大小為3個雙字,帶資料。
FetchAdd 0b010、0b011 0b0 1100 Fetch and Add原子操作。
Swap 0b010、0b011 0b0 1101 Swap原子操作。
CAS 0b010、0b011 0b0 1110 CAS原子操作。
LPrfx 0b100 0b0 L3L2L1L0 Local TLP Prefix
EPrfx 0b100 0b1 E3E2E1E0 End-End TLP Prefix

由上表所示,儲存器讀和寫請求,IO讀和寫請求,及配置讀和寫請求的type欄位相同,如儲存器讀和寫請求的Type欄位都為0b0 0000。此時PCIe匯流排規範使用Fmt欄位區分讀寫請求,當Fmt欄位是“帶資料”的報文,一定是“寫報文”;當Fmt欄位是“不帶資料”的報文,一定是“讀報文”。

PCIe匯流排的資料報文傳送方式與PCI匯流排資料傳送有類似之處。其中儲存器寫TLP使用Posted方式進行傳送,而其他匯流排事務使用Non-Posted方式。

PCIe匯流排規定所有Non-Posted儲存器請求使用Split匯流排方式進行資料傳遞。當PCIe裝置進行儲存器讀、I/O讀寫或者配置讀寫請求時,首先向目標裝置傳送資料讀寫請求TLP,當目標裝置收到這些讀寫請求TLP後,將資料和完成資訊通過完成報文(Cpl或者CplD)傳送給源裝置。

其中儲存器讀、I/O讀和配置讀需要使用CplD報文,因為目標裝置需要將資料傳遞給源裝置;而I/O寫和配置寫需要使用Cpl報文,因為目標裝置不需要將任何資料傳遞給源裝置,但是需要通知源裝置,寫操作已經完成,資料已經成功地傳遞給目標裝置。

在PCIe匯流排中,進行儲存器或者I/O寫操作時,資料與資料包頭一起傳遞;而進行儲存器或者I/O讀操作時,源裝置首先向目標裝置傳送讀請求TLP,而目標裝置在準備好資料後,向源裝置發出完成報文。

PCIe匯流排規範還定義了MRdLk報文,該報文的主要作用是與PCI匯流排的鎖操作相相容,但是PCIe匯流排規範並不建議使用者使用這種功能,因為使用這種功能將極大影響PCIe匯流排的資料傳送效率。

與PCI匯流排並不相同,PCIe匯流排規範定義了Msg報文,即訊息報文。分別為Msg和MsgD,這兩種報文的區別在於一個報文可以傳遞資料,一個不能傳遞資料。

PCIe V2.1匯流排規範還補充了一些匯流排事務,如FetchAdd、Swap、CAS、LPrfx和EPrfx。其中LPrfx和EPrfx匯流排事務分別與Local TLP Prefix和EP-EP TLP Prefix對應。在PCIe匯流排規範V2.0中,TLP頭的大小為1DW,而使用LPrfx和EPrfx匯流排事務可以對TLP頭進行擴充套件,本節不對這些TLP Prefix做進一步介紹。PCIe裝置可以使用FetchAdd、Swap和CAS匯流排事務進行原子操作。

2、TC欄位

TC欄位表示當前TLP的傳送型別,PCIe匯流排規定了8種傳輸型別,分別為TC0~TC7,預設值為TC0,該欄位與PCIe的QoS相關。PCIe裝置使用TC區分不同型別的資料傳遞,而多數EP中只含有一個VC,因此這些EP在傳送TLP時,也僅僅使用TC0,但是有些對實時性要求較高的EP中,含有可以設定TC欄位的暫存器。

在Intel的高精度音效卡控制器(High Definition Audio Controller)的擴充套件配置空間中含有一個TCSEL暫存器。系統軟體可以設定該暫存器,使音效卡控制器發出的TLP使用合適的TC。音效卡控制器可以使用TC7傳送一些對實時性要求較強的控制資訊,而使用TC0傳送一般的資料資訊。在具體實現中,一個EP也可以將控制TC欄位的暫存器放入到裝置的BAR空間中,而不必和Intel的高精度音效卡控制器相同,存放在PCI配置空間中。

目前許多處理器系統的RC僅支援一個VC通路,此時EP使用不同的TC進行傳遞資料的意義不大。x86處理器的MCH中一般支援兩個VC通路,而多數PowerPC處理器僅支援一個VC通路。PLX公司的多數Switch也僅支援兩個VC通路。

有些RC,如MPC8572處理器,也能決定其發出TLP使用的TC。在該處理器的PCIe Outbound視窗暫存器(PEXOWARn)中,含有一個TC欄位,通過設定該欄位可以確定RC發出的TLP使用的TC欄位。不同的TC可以使用PCIe鏈路中的不同VC,而不同的VC的仲裁級別並不相同。EP或者RC通過調整其發出TLP的TC欄位,可以調整TLP使用的VC,從而調整TLP的優先順序。

3、Attr欄位

Attr欄位由3位組成,其中第2位表示該TLP是否支援PCIe匯流排的ID-based Ordering;第1位表示是否支援Relaxed Ordering;而第0位表示該TLP在經過RC到達儲存器時,是否需要進行Cache共享一致性處理。Attr欄位如圖5 3所示。

一個TLP可以同時支援ID-based Ordering和Relaxed Ordering兩種位序。Relaxed Ordering最早在PCI-X匯流排規範中提出,用來提高PCI-X匯流排的資料傳送效率;而ID-based Ordering由PCIe V2.1匯流排規範提出。TLP支援的序如表5 3所示。

表5 3 TLP支援的序

Attr[2] Attr[1] 型別
0 0 預設序,即強序模型
0 1 PCI-X Relaxed Ordering模型
1 0 ID-Based Ordering(IDO)模型
1 1 同時支援Relaxed Ordering和IDO模型

當使用標準的強序模型時,在資料的整個傳送路徑中,PCIe裝置在處理相同型別的TLP時,如PCIe裝置傳送兩個儲存器寫TLP時,後面的儲存器寫TLP必須等待前一個儲存器寫TLP完成後才能被處理,即便當前報文在傳送過程中被阻塞,後一個報文也必須等待。如果使用Relaxed Ordering模型,後一個儲存器寫TLP可以穿越前一個儲存器寫TLP,提前執行,從而提高了PCIe匯流排的利用率。有時一個PCIe裝置發出的TLP,其目的地址並不相同,可能先進入傳送佇列的TLP,在某種情況下無法傳送,但這並不影響後續TLP的傳送,因為這兩個TLP的目的地址並不相同,傳送條件也並不相同。值得注意的是,在使用PCI匯流排強序模型時,不同種類的TLP間也可以亂序通過同一條PCIe鏈路,比如儲存器寫TLP可以超越儲存器讀請求TLP提前進行。而PCIe匯流排支援Relaxed Ordering模型之後,在TLP的傳遞過程中出現亂序種類更多,但是這些亂序仍然是有條件限制的。在PCIe匯流排規範中為了避免死鎖,還規定了不同報文的傳送資料規則,即Ordering Rules。

PCIe V2.1匯流排規範引入了一種新的“序”模型,即IDO(ID-Based Ordering)模型,IDO模型與資料傳送的資料流相關,是PCIe V2.1規範引入的序模型。

Attr欄位的第0位是“No Snoop Attribute”位。當該位為0時表示當前TLP所傳送的資料在通過FSB時,需要與Cache保持一致,這種一致性由FSB通過匯流排監聽自動完成而不需要軟體干預;如果為1,表示FSB並不會將TLP中的資料與Cache進行一致,在這種情況下,進行資料傳送時,必須使用軟體保證Cache的一致性。

在PCI匯流排中沒有與這個“No Snoop Attribute”位對應的概念,因此一個PCI裝置對儲存器進行DMA操作時會進行Cache一致性操作(1) ,這種“自動的”Cache一致性行為在某些特殊情況下並不能帶來更高的效率。

當一個PCIe裝置對儲存器進行DMA讀操作時,如果傳送的資料非常大,比如512MB,Cache的一致性操作不但不會提高DMA寫的效率,反而會降低。因為這個DMA讀訪問的資料在絕大多數情況下,並不會在Cache中命中,但是FSB依然需要使用Snoop Phase進行匯流排監聽。而處理器在進行Cache一致性操作時仍然需要佔用一定的時鐘週期,即在Snoop Phase中佔用的時鐘週期,Snoop Phase是FSB匯流排事務的一個階段,如圖3 6所示。

對於這類情況,一個較好的做法是,首先使用軟體指令保證Cache與主儲存器的一致性,並置“No Snoop Attribute”位為1(2),然後再進行DMA讀操作。同理使用這種方法對一段較大的資料區域進行DMA寫時,也可以提高效率。

除此之外,當PCIe裝置訪問的儲存器,不是“可Cache空間”時,也可以通過設定“No Snoop Attribute”位,避免FSB的Cache共享一致性操作,從而提高FSB的效率。“No Snoop Attribute”位是PCIe匯流排針對PCI匯流排的不足,所作出的重要改動。

4、通用TLP頭中的其他欄位

除了Fmt和Type欄位外,通用TLP頭還含有以下欄位。

4.1、TH位、TD位和EP位

TH位為1表示當前TLP中含有TPH(TLP Processing Hint)資訊,TPH是PCIe V2.1匯流排規範引入的一個重要功能。TLP的傳送端可以使用TPH資訊,通知接收端即將訪問資料的特性,以便接收端合理地預讀和管理資料。

TD位表示TLP中的TLP Digest是否有效,為1表示有效,為0表示無效。而EP位表示當前TLP中的資料是否有效,為1表示無效,為0表示有效。

4.2、 AT欄位

AT欄位與PCIe匯流排的地址轉換相關。在一些PCIe裝置中設定了ATC(Address Translation Cache)部件,這個部件的主要功能是進行地址轉換。只有在支援IOMMU技術的處理器系統中,PCIe裝置才能使用該欄位。

AT欄位可以用作儲存器域與PCI匯流排域之間的地址轉換,但是設定這個欄位的主要目的是為了方便多個虛擬主機共享同一個PCIe裝置。對這個欄位有興趣的讀者可以參考Address Translation Sevices規範,這個規範是PCI的IO Virtualization規範的重要組成部分。對虛擬化技術有興趣的讀者可以參考清華大學出版社的《系統虛擬化——原理與實現》,以獲得基本的關於虛擬化的入門知識。

4.3、Length欄位

Length欄位用來描述TLP的有效負載(Data Payload)大小(3).PCIe匯流排規範規定一個TLP的Data Payload的大小在1B~4096B之間。PCIe匯流排設定Length欄位的目的是提高匯流排的傳送效率。

當PCI裝置在進行資料傳送時,其目標裝置並不知道實際的資料傳送大小,這在一定程度上影響了PCI匯流排的資料傳送效率。而在PCIe匯流排中,目標裝置可以通過Length欄位提前獲知源裝置需要傳送或者請求的資料長度,從而合理地管理接收緩衝,並根據實際情況進行Cache一致性操作。

當PCI裝置進行DMA寫操作,將PCI裝置中4KB大小的資料傳送到主儲存器時,這個PCI裝置的DMA控制器將存放傳送的目的地址和傳送大小,然後啟動DMA寫操作,將資料寫入到主儲存器。由於PCI匯流排是一條共享匯流排,因此傳送4KB大小的資料,可能會使用若干個PCI匯流排寫事務才能完成(4),而每一個PCI匯流排寫事務都不知道DMA控制器何時才能將資料傳送完畢。

如果這些匯流排寫事務還通過一系列PCI橋才能到達儲存器,在這個路徑上的每一個PCI橋也無法預知,何時這個DMA操作才能結束。這種“不可預知”將導致PCI匯流排的頻寬不能被充分利用,而且極易造成PCI橋資料緩衝的浪費。

而PCIe匯流排通過TLP的Length欄位,可以有效避免PCIe鏈路頻寬的浪費。值得注意的是,Length欄位以DW為單位,其最小單位為1個DW。如果PCIe主裝置傳送的單位小於1個DW或者傳送的資料並不以DW對界時,需要使用位元組使能欄位,即“DW BE”欄位。


(1)PowerPC處理器通過設定Inbound暫存器,也可以避免這個Cache一致性操作。(2)FSB收到這類TLP後,不進行Cache一致性操作。(3)儲存器讀請求TLP沒有DataPayload欄位,此時該TLP使用Length欄位表示需要讀取多少資料。(4)當多個PCI裝置共享一條PCI匯流排時,一個裝置不會長時間佔用PCI匯流排,這個裝置在使用這條PCI匯流排一定的時間後,將讓出PCI匯流排的使用權。