017 PCIe匯流排的事務層(一)
一、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匯流排的使用權。