5.3 存儲器、I/O和配置讀寫請求TLP
本節講述PCIe總線定義的各類TLP,並詳細介紹這些TLP的格式。在這些TLP中,有些格式對於初學者來說較難理解。讀者需要建立PCIe總線中與TLP相關的一些基本概念,特別是存儲器讀寫相關的報文格式。在PCIe總線中,存儲器讀寫,I/O讀寫和配置讀寫請求TLP由以下幾類報文組成。
(1) 存儲器讀請求TLP和讀完成TLP
當PCIe主設備,RC或者EP,訪問目標設備的存儲器空間時,使用Non-Posted總線事務向目標設備發出存儲器讀請求TLP,目標設備收到這個存儲器讀請求TLP後,使用存儲器讀完成TLP,主動向主設備傳遞數據。當主設備收到目標設備的存儲器讀完成TLP後,將完成一次存儲器讀操作。
(2) 存儲器寫請求TLP
在PCIe總線中,存儲器寫使用Posted總線事務。PCIe主設備僅使用存儲器寫請求TLP即可完成存儲器寫操作,主設備不需要目標設備的回應報文。
(3) 原子操作請求和完成報文
原子操作由PCIe V2.1總線規範引入,一個完整的原子操作包括原子操作請求和原子操作完成報文組成。原子操作的使用方法與其他Non-Posted總線事務類似,首先PCIe主設備向目標設備發送原子操作請求,之後目標設備向主設備發送原子操作完成報文,結束一次原子操作。有關原子操作的詳細說明見第5.3.5節。
(4) I/O讀寫請求TLP和讀寫完成TLP
在PCIe總線中,I/O讀寫操作使用Non-Posted總線事務,I/O讀寫TLP都需要完成報文做為回應。隻是在I/O寫請求的完成報文中不需要“帶數據”,而僅含有I/O寫請求是否成功的狀態信息。
(5) 配置讀寫請求TLP和配置讀寫完成TLP
從總線事務的角度上看,配置讀寫請求操作的過程與I/O讀寫操作的過程類似。配置讀寫請求TLP都需要配置讀寫完成作為應答,從而完成一個完成的配置讀寫操作。
(6) 消息報文
與PCI總線相比,PCIe總線增加了消息請求事務。PCIe總線使用基於報文的數據傳送模式,所有總線事務都是通過報文實現的,PCIe總線取消了一些在PCI總線中存在的邊帶信號。在PCIe總線中,一些由PCI總線的邊帶信號完成的工作,如中斷請求和電源管理等,在PCIe總線中由消息請求報文實現。
5.3.1 存儲器讀寫請求TLP
存儲器讀寫請求TLP的格式如圖5?8所示。
在PCIe總線中,存儲器寫請求TLP使用Posted數據傳送方式。而其他與存儲器和I/O相關的報文都使用Split方式進行數據傳送,這些請求報文需要完成報文,通知發送端之前的數據請求報文已經被處理完畢,有關完成報文的詳細說明見第5.3.2節。
存儲器讀寫請求TLP使用地址路由方式進行數據傳遞,在這類TLP頭中包含Address字段,Address字段具有兩種地址格式,分別是32位和64位地址。在存儲器讀寫和I/O讀寫請求的第3和第4個雙字中,存放TLP的32或者64位地址。存儲器、I/O和原子操作讀寫請求使用的TLP頭較為類似。本節僅介紹存儲器、I/O讀寫使用的TLP頭,而在第5.3.5節詳細介紹原子操作。
1 Length字段
在存儲器讀請求TLP中並不包含Data Payload,在該報文中,Length字段表示需要從目標設備數據區域讀取的數據長度;而在存儲器寫TLP中,Length字段表示當前報文的Data Payload長度。
Length字段的最小單位為DW。當該字段為n時,表示需要獲得的數據長度或者當前報文的數據長度為n個DW,其中0?n?0x3FF。值得注意的是,當n等於0時,表示數據長度為1024個DW。
2 DW BE字段
PCIe總線以字節為基本單位進行數據傳遞,但是Length字段以DW為最小單位。為此TLP使用Last DW BE和First DW BE這兩個字段進行字節使能,使得在一個TLP中,有效數據以字節為單位。
這兩個DW BE字段各由4位組成,其中Last DW BE字段的每一位對應數據Payload最後一個雙字的字節使能位;而First DW BE字段的每一位對應數據Payload第一個雙字的字節使能位。其對應關係如表5?5所示。
表5?5 First和Last DW BE字段
Last DW BE | 第3位 | 為1表示數據Payload的最後一個雙字的字節3有效 |
第2位 | 為1表示數據Payload的最後一個雙字的字節2有效 |
|
第1位 | 為1表示數據Payload的最後一個雙字的字節1有效 |
|
第0位 | 為1表示數據Payload的最後一個雙字的字節0有效 |
|
First DW BE | 第3位 | 為1表示數據Payload的第一個雙字的字節3有效 |
第2位 | 為1表示數據Payload的第一個雙字的字節2有效 |
|
第1位 | 為1表示數據Payload的第一個雙字的字節1有效 |
|
第0位 | 為1表示數據Payload的第一個雙字的字節0有效 |
Last DW BE和First DW BE這兩個字段的使用規則如下。
- 如果傳送的數據長度在一個對界的雙字(DW)之內,則Last DW BE字段為0b0000,而First DW BE的對應位置1;如果數據長度超過1DW,Last DW BE字段一定不能為0b0000。PCIe總線使用Last DW BE字段為0b0000表示所傳送的數據在一個對界的DW之內。
- 如果傳送的數據長度超過1DW,則First DW BE字段至少有一個位使能。不能出現First DW BE為0b0000的情況。
- 如果傳送的數據長度大於等於3DW,則在First DW BE和Last DW BE字段中不能出現不連續的置1位。
- 如果傳送的數據長度在1DW之內時,在First DW BE字段中允許有不連續的置1位。此時PCIe總線允許在TLP中傳送1個DW的第1,3字節或者第0,2字節。
- 如果傳送的數據長度為2DW之內時,則First DW BE字段和Last DW BE字段允許有不連續的置1位。
值得注意的是,PCIe總線支持一種特殊的讀操作,即“Zero-Length”讀請求。此時Length字段的長度為1DW,而First DW BE字段和Last DW BE字段都為0b0000,即所有字節都不使能。此時與這個存儲器讀請求TLP對應的讀完成TLP中不包含有效數據。再次提醒讀者注意“Zero-Length”讀請求使用的Length字段為1,而不是為0,為0表示需要獲得的數據長度為1024個DW。
“Zero-Length”讀請求的引入是為了實現“讀刷新”操作,該操作的主要目的是為了確保之前使用Posted方式所傳送的數據,到達最終的目的地,與“Zero-Length”讀對應的讀完成報文中不含有負載,從而提高了PCIe鏈路的利用率。
在PCIe總線中,使用Posted方式進行存儲器寫時,目標設備不需要向主設備發送回應報文,因此主設備並不知道這個存儲器寫是否已經達到目的地。而主設備可以使用“讀刷新”操作,向目標設備進行讀操作來保證存儲器寫最終到達目的地。
在PCIe總線中,標準的存儲器讀請求也可以完成同樣的刷新操作。但是“Zero-Length”讀請求與這種讀請求相比,其完成報文不需要“Data Payload”,因此在一定程度上提高了PCIe總線的效率。如果一個存儲器讀請求TLP報文的TH位為1時,DW BE字段將被重新定義為ST[7:0]字段,有關ST字段的詳細說明見第5.3.6節。
3 Requester ID字段
Requester ID字段包含“生成這個TLP報文”的PCIe設備的總線號(Bus Number)、設備號(Device Number)和功能號(Function Number),其格式如圖5?9所示。對於存儲器寫請求TLP,Requester ID字段並不是必須的,因為目標設備收到存儲器寫請求TLP後,不需要完成報文作為應答,因此Requester ID字段對於存儲器寫請求TLP並沒有實際意義。
但是PCIe總線規範並沒有明確說明存儲器寫請求TLP究竟需不需要Requester ID字段,為此IC設計者依然需要將存儲器寫TLP的Requester ID字段置為有效。值得注意的是,如果一個存儲器寫請求TLP報文的TH位為1時,Tag字段將被重新定義為ST[7:0]字段,有關ST字段的詳細說明見第5.3.6節。
對於Non-Posted數據請求,目標設備需要使用完成報文做為回應。在這個完成報文中,需要使用源設備的Requester ID字段。因此在Non-Posted數據請求TLP中,如存儲器讀請求、I/O和配置讀寫請求TLP,必須使用Requester ID字段。
存儲器,I/O讀請求TLP中含有Requester ID和Tag字段。在PCIe總線中Requester ID和Tag字段合稱為Transaction ID,Transaction ID字段的格式如圖5?9所示。存儲器讀,I/O和配置讀寫請求TLP使用Transaction字段的主要目的是使接收端通過分析報文的Transaction ID,確認完成報文的目的地。
在PCIe總線中,所有Non-Posted數據請求都需要完成報文作為應答,才能結束一次完整的數據傳遞。一個源設備在發送Non-Posted數據請求之後,如果並沒有收到目標設備回送的完成報文,TLP報文的發送端需要保存這個Non-Posted數據請求,此時該設備使用的Transaction ID(Tag字段)不能被再次使用,直到一次數據傳送結束,即數據發送端收齊與該TLP對應的所有完成報文。
PCIe設備發出的每一個Non-Posted數據請求TLP,在同一個時刻段內Transaction ID必須是唯一的。即在同一時間段內,在當前PCI總線域中不能存在兩個或者兩個以上的存儲器讀請求TLP,其Transaction ID完全相同。
源設備發送Non-Posted數據請求後,在沒有獲得全部完成報文之前,不能釋放這個Transaction ID占用的資源。在同一個PCIe設備發送的TLP中,其Requester ID字段是相同的,因此PCIe設備的設計者所能管理的資源是Tag字段。PCIe設備的設計者需要合理地管理Tag資源,以保證數據傳送的正確性。
PCIe設備在發送Non-Posted數據請求時,需要暫存這些Non-Posted數據請求。其中Tag字段的長度決定了發送端能夠暫存多少個同類型的TLP,如果Tag字段長度為5,發送端能夠暫存32個報文;如果PCIe設備使能了Extended Tag位,Tag字段可以由8位組成,此時發送端能夠暫存256個報文。
通過Tag字段的長度,可以發現每個PCIe設備最多可以暫存256個同類型的Non-Posted報文。但是在多數情況下,一個PCIe設備可能隻包含1個Function。因此PCIe設備還可以使用Function號擴展Tag字段,從而擴展“暫存TLP報文”的數目。
PCIe設備在PCI Express Capability結構的Device Control寄存器中,設置了一個Phantom Functions Enable位,。當一個PCIe設備僅支持一個Function時,Phantom Functions Enable位可以被設置為1,此時PCIe設備可以使用Requester ID的Function Number字段對Tag字段進一步擴展,此時一個PCIe設備最多可以支持2048個同類型的數據請求。
由以上分析可以發現,一個PCIe設備最多可以支持2048個存儲器讀數據請求,基本上可以滿足絕大多數需要。但是在某些特殊應用場合,PCIe設備即使可以暫存2048個存儲器讀請求,也並不足夠。
與PCI總線相比,PCIe總線的數據傳送延時較長,而為了彌補這個傳送延時,PCIe設備通常使用流水線技術。此時PCIe設備必須能夠連續發送多個存儲器讀請求報文,隨後RC也將連續回送多個存儲器讀完成報文,在PCIe設備的實現中,需要保證能夠源源不斷地從RC接收這些報文,以充分利用報文接收流水線,。
PCIe V2.1總線規範還提出了另一種Requester ID格式,即ARI (Alternative Routing-ID Interpretation)格式,除了Requester ID外,在完成報文中使用的Completer ID也可以使用這種格式。ARI格式將ID號分為兩個字段,分別為Bus號和Function號,而不使用Device號,ARI格式如圖5?10所示。
PCIe總線引入ARI格式的依據是在一個PCIe鏈路上僅可能存在一個PCIe設備,因而其Device號一定為0。在多數PCIe設備中,Requester ID和Completion ID包含的Device號是沒有意義的。使用ARI格式時,一個PCIe設備最多可以支持256個Function,而傳統的PCIe設備最多隻能支持8個Function。
4 I/O讀寫請求TLP的規則
I/O讀寫請求與存儲器讀寫請求TLP的格式基本類似,隻是I/O讀寫請求TLP隻能使用32位地址模式和基於地址的路由方式,而且I/O讀寫請求TLP隻能使用Non-Posted方式進行傳遞。PCIe總線並不建議PCIe設備支持I/O地址空間,但是Switch和RC需要具備接收和發送I/O請求報文的能力,因為許多老的PCI設備依然使用I/O地址空間,這些PCI設備可以通過PCIe橋連接到PCIe總線中。因此雖然支持I/O讀寫請求的PCIe設備極少,但是在PCIe體係結構中,依然需要支持PCI總線域的I/O地址空間。
與存儲器讀寫請求TLP不同,I/O讀寫請求TLP的某些字段必須為以下值。
- TC[2:0]必須為0,I/O請求報文使用的TC標簽隻能為0。
- TH和Attr2位保留,而Attr[1:0]必須為“0b00”,這表示I/O請求報文必須使用PCI總線的強序數據傳送模式,而且在傳送過程中,硬件保證其傳送的數據與Cache保持一致,實際上I/O地址空間都是不可Cache的。
- AT[1:0]必須為“0b00”,表示不支持地址轉換,因此在虛擬化技術中,並不處理PCI總線域中的I/O空間。
- Length[9:0]為“0b00 0000 0001”,表示I/O讀寫請求TLP最大的數據Payload為1DW,該類TLP不支持突發傳送。
- Last DW[3:0]為“0b0000”。
5.3.2 完成報文
PCIe總線支持Split傳送方式,目標設備使用完成報文向源設備主動發送數據。完成報文使用ID路由方式,由TLP Predix、報文頭和Data Payload組成,但是在某些完成報文可以不含有Data Payload,如I/O或者配置寫完成和Zero-Length讀完成報文。在PCIe總線中,有一下幾類數據請求需要收到完成報文之後,才能完成整個數據傳送過程,完成報文格式如圖5?11所示。
- 所有的數據讀請求,包括存儲器、I/O讀請求、配置讀請求和原子操作請求。當一個PCIe設備發出這些數據請求報文後,必須收到目標設備的完成報文後,才能結束一次數據傳送。這一類完成報文必須包含Data Payload。
- 所有的Non-Posted數據寫請求,包括I/O和配置寫請求。當一個PCIe設備發出這些數據請求報文後,必須收到目標設備的完成報文後,才能結束數據傳送。但是這一類完成報文不包含數據,僅包含應答信息。
- 與ATS機製相關的一些報文。
完成報文“Byte 0”中的大部分字段與“存儲器,I/O、配置請求報文”的對應字段的含義相同。完成報文一次最多能夠傳送的報文大小不能超過Max_Payload_Size參數。在多數處理器中,完成報文中包含的數據在一個Cache行之內,完成報文使用RCB參數來處理數據對界,RCB參數的大小與處理器係統的Cache行長度和DDR-SDRAM的一次突發傳送長度相關,這些參數的詳細描述見第5.4.3節。在x86和PowerPC處理器中,一個存儲器讀完成報文一般不超過RCB參數。
1 Requester ID和Tag字段
完成報文使用ID路由方式,ID路由方式詳見第5.2.2節。完成報文頭的長度為3DW,完成報文頭中包含Transaction ID信息,由Requester ID和Tag字段組成,這個ID必須與源設備發送的數據請求報文的Transaction ID對應,完成報文使用Transaction ID進行ID路由,並將數據發送給源設備。
當PCIe設備收到存儲器讀、I/O讀寫或者配置讀寫請求TLP時,需要首先保存這些報文的Transaction ID,之後當該設備準備好完成報文後,將完成報文的Requester ID和Tag字段賦值為之前保存的Transaction ID字段。
2 Completer ID字段
Completer ID字段的含義與Requester ID字段較為相似,隻是該字段存放“發送完成報文”的PCIe設備的ID號。PCIe設備進行數據請求時需要在TLP字段中包含Requester ID字段;而使用完成報文結束數據請求時,需要提供Completer ID字段。
3 Status字段
Status字段保存當前完成報文的完成狀態,表示當前TLP是正確地將數據傳遞給數據請求端;還是在數據傳遞過程中出現錯誤;或者要求數據請求方進行重試。PCIe總線規定了幾類完成狀態,如表5?6所示。
表5?6 Status字段
Status[2:0] | 描述 |
0b000 | SC(Sucessful Completion),正常結束 |
0b001 | UR(Unsupported Request),不支持的數據請求 |
0b010 | CRS(Configuration Request Retry Status),要求數據請求方進行重試。當RC對一個PCIe目標設備發起配置請求時,如果該目標設備沒有準備好,可以向RC發出CRS完成報文,當RC收到這類報文時,不能結束本次配置請求,必須擇時重新發送配置請求 |
0b100 | CA(Completion Abort),數據夭折。表示目標設備無法完成本次數據請求 |
其他 | 保留 |
4 BCM位與Byte Count字段
BCM(Byte Count Modified)字段由PCI-X設備設置。PCI-X設備也支持Split Transaction傳送方式,當PCI-X設備進行存儲器讀請求時,目標設備不一定一次就能將所有數據傳遞給源設備。此時目標設備在進行第一次數據傳送時,需要設置Byte Count字段和BCM位。
BCM位表示Byte Count字段是否被更改,該位僅對PCI-X設備有效,而PCIe設備不能操縱BCM位,隻有PCI-X設備或者PCIe-to-PCI-X橋可以改變該位。本節對此位不做進一步介紹,對此位感興趣的讀者可以參考PCI-X Addendum to the PCI Local Bus Specification, Revision 2.0。
Byte Count字段記錄源設備還需要從目標設備中,獲得多少字節的數據就能完成全部數據傳遞,當前TLP中的有效負載也被Byte Count字段統計在內。該字段由12位組成。該字段為0b0000-0000-0001表示還剩一個字節,為0b1111-1111-1111表示還剩4095個字節,而為0b0000-0000-0000表示還剩4096個字節。除了存儲器讀請求的完成報文外,大多數完成報文的Byte Count字段為4。
如一個源設備向目標設備發送一個“讀取128B的存儲器讀請求TLP”,而目標設備收到這個讀請求TLP後,可能使用兩個存儲器讀完成TLP傳遞數據。其中第1個存儲器讀完成TLP的有效數據為64B,而Byte Count字段為128;第2個存儲器讀完成TLP中的有效數據為64B,而Byte Count字段也為64。當數據請求端接收完畢第1個存儲器讀完成TLP後,發現還有64B的數據沒有接收完畢,此時必須等待下一個存儲器讀完成TLP。等到數據請求端收齊所有數據後,才能結束整個存儲器讀請求。
目標設備發出的第2個讀完成TLP中的有效數據為64B,而Byte Count字段為64,當數據請求端接收完畢這個讀完成TLP後,將完成一個完整的存儲器讀過程,從而可以釋放這個存儲器讀過程使用的Tag資源。存儲器讀請求的完成報文的拆分方式較為複雜,Byte Count字段的設置也相對較為複雜。
5 Lower Address字段
如果當前完成報文為存儲器讀完成TLP,該字段存放在存儲器讀完成TLP中第一個數據所對應地址的最低位。值得注意的是,在完成報文中,並不存在First DW BE和Last DW BE字段,因此接收端必須使用存儲器讀完成TLP的Low Address字段,識別一個TLP中包含數據的起始地址。
5.3.3 配置讀寫請求TLP
配置讀寫請求TLP由RC發起,用來訪問PCIe設備的配置空間。配置請求報文使用基於ID的路由方式。PCIe總線也支持兩種配置請求報文,分別為Type 00h和Type 01h配置請求。配置請求TLP的格式如圖5?12所示。
配置請求TLP的第4~7字節與存儲器請求TLP類似。而第8~11字節的Bus、Device和Function Number中存放該TLP訪問的目標設備的相應的號碼,而Ext Register和Reigister Number存放寄存器號。配置請求報文的其他字段必須為以下值。
- TC[2:0]必須為0,I/O請求報文的傳送類型(TC)隻能為0。
- TH位為保留位;Attr2位為保留,而Attr[1:0]必須為“00b”,這表示I/O請求報文使用PCI總線的強序數據傳送模式;AT[1:0]必須為“0b00”,表示不進行地址轉換。
- Length[9:0]為“0b00 0000 0001”,表示配置讀寫請求最大Payload為1DW。
- Last DW BE字段為“0b0000”。而First DW BE字段根據配置讀寫請求的大小設置。
5.3.4 消息請求報文
在PCIe總線中,多數消息報文使用隱式路由方式,其格式如圖5?13所示。其中Byte 0字段為通用TLP頭,而Byte 4的第3字節中存放Message Code字段。
PCIe總線規定了以下幾類消息報文。
- INTx中斷消息報文(INTx Interrupt Signaling)。
- 電源管理消息報文(Power Management)。
- 錯誤消息報文(Error Signaling)。
- 鎖定事務消息報文(Locked Transaction Support)。
- 插槽電源限製消息報文(Slot Power Limit Support)。
- Vendor-Defined Messages。
最後更新:2017-04-03 16:48:40