PCIe 體系結構簡介

PCIe的歷史

PCIe是在PCI(Peripheral Component Interconnect)的基礎上發展而來的。而PCI則是Intel在1992年提出的一套總線協議,並召集其它的小夥伴組成瞭名為 PCI-SIG (PCI Special Interest Group)(PCI 特殊興趣組)的企業聯盟。 這個組織就負責PCI和其繼承者們(PCI-X和PCIe的標準制定和推廣)。

PCI的提出是為瞭解決當時的ISA/EISA,MCA,VLB等總線速度太慢,接口混亂不統一而提出的,因為它的統一和開放,PCI獲得瞭廠商的歡迎和支持,各種PCI設備應運而生豐富瞭PC的生態。雖然PCI總線獲得瞭巨大的成功,但是隨著CPU主頻的不斷提高,PCI總線的帶寬越來越難以滿足要求。PCI總線不斷的升級從32位/33MHz擴展到64位/64MHz,PCI-X甚至提升到瞭533MHz,最大理論帶寬為4263MB。但是仍然無法解決其體系結構中存在的一些先天不足:

  1. PCI是共享總線,總線上的所有設備必須共享帶寬,另外總線協議還有一些開銷,雖然64位/64MHz理論上可以提供最大帶寬為532MB,但是實際可以利用的數據帶寬遠低於峰值。
  2. PCI總線是並行的,它通過提高總線頻率和位寬的方式增加傳輸帶寬,但是這種方式的性價比比較低,因為位寬的增加需要更多的芯片管腳,從而導致64位的芯片價格遠高於32位,另外在主板設計的時候也需要更多層的PCB實現64位芯片接口,增加成本和佈線 難度;而且因為頻率和位寬的增加帶來瞭信號完整性的問題,也影響瞭總線的負載能力。比如33MHz的總線可以驅動10個負載,66MHz的總線最多隻能渡情4個負載。
  3. PCI總線並沒有考慮服務質量QoS,因為PCI總線是並行的主從式的總線,總線上的設備隻能輪流使用PCI總線,當一個設備長期占用總線時將阻止其他設備對總線的使用但是有些實時的設備如數據采集卡,音頻或者視頻的應用需要額定的帶寬,因此就沒法得0以 滿足。

PCIe如何解決PCI體系結構存在的問題的呢?

  1. PCIe使用瞭高速差分總線端到端的連接方式替代並行總線,與並行總線相比高速差分信號可以使用更高的時鐘頻率,而且更少的信號線實現之前需要更多的芯片管腳才能實現的總線帶寬,而且與單端信號相比差分信號的抗幹擾能力更強。
  2. PCIe使用瞭網絡通信中使用的技術如基於多種數據路由方式,報文數據傳送,以及Traffic class和virtual channel結束數據傳輸過程中的QoS問題。
  3. PCIe的鏈路可以由多條Lane組成,換句話來說它的性能可擴展。可以像搭積木一樣增加Lane或者減少Lane的組合來提高性能。
  4. PCIe總線在系統軟件編程上和PCI總線兼容,絕大多數的PCI總線事務都被PCIe總線保留,PCI設備的配置空間也被PCIe繼承。

PCIe總線基礎

PCIe 從2003年的1.0版本開始到現在的6.0經歷瞭數次更新,速度從2.5GT/s提升到瞭65GT/s。

PCIe采用瞭端到端的全雙工的傳輸設計,基於數據包的傳輸,設備之間通過link相連,link支持1到32個通道(lane)。

每個鏈路可以包含多達32個通道。

PCIe 采用瞭差分信號對數據進行收發,以提高總線的性能 。 除瞭差分總線,PCIe還引入瞭嵌入式時鐘的技術(Embedded Clock),即發送端不再向接收端發送時鐘,但是接收端可以通過8b/10b,128b/130b的編碼從數據Lane中恢復出時鐘。

PCIe總線的層次結構

PCIe使用串行的基於數據包的傳輸方式,這種方式有效的去除瞭PCI總線中存在的一些sideband信號如INT#,PME#。 PCIe總線是分層實現的,它包含多個層次,從上到下分別是應用層(也就是下圖中的Device Core,PCIe Core HW/SW Interface),事務層(Transaction Layer),數據鏈路層(Data Link Layer),物理層(Physical Layer),其中,應用層並不是PCIe Spec所規定的內容,完全由用戶根據自己的需求進行設計,另外三層都是PCIe Spec明確規范的,並要求設計者嚴格遵循的。PCIe的層次結構有點類似TCP/IP的協議實現,不過PCIe的各個層次都是通過硬件邏輯實現的。發送時數據報文先由應用層產生,然後經過事務層,數據鏈路層和物理層最終發送出去。接收端則是相反的一個步驟,數據先經過物理層,然後向上送給數據鏈路層,事務層,最後到達應用層。

  • 事務層PCIe事務層定義瞭總線所使用的事務,其中大部分都與PCI總線兼容在PCIe Spec中,規定瞭四種類型的請求(Request):Memory、IO、Configuration和Messages。其中,前三種都是從PCI/PCI-X總線中繼承過來的,第四種Messages是PCIe新增加的類型。事務層接收來自核心層的數據並將其封裝成TLP(Transaction Layer Packet)發向數據鏈路層。另外事務層也可以從數據鏈路層接收數據報文,然後轉發到核心層。

  • 數據鏈路層數據鏈路層接收來自事務層的數據報文,添加Sequence Number前綴和CRC後綴。數據鏈路層使用ACK/NAK協議保證報文的可靠傳遞。另外它還定義瞭多種DLLP(Data Link Layer Pakcet),DLLP 產生於數據鏈路層結束於數據鏈路層。DLLP於TLP並不相同,DLLP不是TLP加上Sequence Number和CRC後綴組成的。

  • 物理層物理層是PCIe總線的最底層,將PCIe設備相互連接在一起。它負責接收和轉發各種數據包(TLP,DLLP)。另外它還創建和解碼一些專門的序列Ordered-Set Packet或者叫做PLP(Physical Layer Packet),這些序列用於同步和管理鏈路。物理層還實現瞭鏈路訓練和初始化的功能,它通過LTSSM來完成(Link Training and Status State Machine)。

PCIe體系的拓撲結構

PCIe作為局部總線主要是用來處理器系統中的外部設備,當然它也可以用來連接其他的處理器系統。在大多數處理器系統中都使用瞭RC,Switch和PCIe-PCI橋等模塊用來連接PCIe和PCI設備。

  • Up/Down Stream PortPCIe spec規定可以與RC直接或者間接相連的端口稱之為上遊端口,在PCIe總線中,RC的位置一般在上方,這也是上遊端口的由來。除上遊端口之外的其它端口就是下遊端口。

  • Root ComplexRC是PCIe體系結構中的一個重要的組成部件,它與PCI總線的中Host bridge有些類似,是CPU和PCIe總線直接的接口。它的主要功能是完成存儲器域到PCIe總線域的地址轉換,隨著虛擬化技術的引入,RC的功能也越來越復雜。RC把來自CPU的request轉化成PCIe的4種不同的requests(configuration, Memory, I/O, Message)並發送給接在它下面的設備。從軟件的角度來看,RC像是一組虛擬的PCI-PCI橋。

  • PCIe Switch & BridgeSwitch提供瞭分散或者是聚合的功能,它允許更多的設備接入到 一個PCIe Port。它扮演瞭數據包路由的功能。Bridge提供瞭一個轉換接口用來連接其他的總線,如PCI/PCI-X。這樣可以允許在PCIe的系統中接入一張舊的PCI設備。
  • PCIe Endpoint它隻有一個上遊端口,位於PCIe拓撲結構的樹的末端。它作為請求的發起者或者完成者。分為Legacy Endpoint和Native Endpoint,Legacy使用PCI總線的操作用於支持向後兼容。

PCIe的軟件編程接口

  • PCIe 配置空間PCI spec規定瞭256字節的配置空間,PCIe總線為瞭兼容PCI設備,幾乎完整的保留瞭PCI總線的配置空間。並將配置空間擴展到瞭4KB,用於支持一些PCIe總線中的新功能,如Capability,power management, MSI等。

PCI設備使用Bus Device Function用來區分不同的設備(簡稱BDF),PCIe也繼承瞭這種編碼方式,另外PCI定瞭以瞭兩種header的格式(配置空間內容不一致),一種是PCI device,另一種是Bridge,同樣PCIe也繼承瞭這種格式。

PCI設備使用IO空間的CF8(Configuration Address Port)/CFC(Configuration Data Port)地址來訪問配置空間。

PCIe將配置空間擴展到4KB,原來CF8/CFC的訪問方式仍然可以訪問所有PCIe配置空間的前256Byte,但是訪問不瞭剩下的空間。所以PCIe引入瞭所謂的增強配置空間訪問機制Enhanced Configuration Access Mechanism,它通過將配置空間映射到MMIO空間,使得對配置空間的訪問就像對內存一樣,也因此可以訪問完整的4KB配置空間。

  • PCIe的枚舉PCI枚舉的過程其實是一個使用深度優先的算法不斷遞歸發現新設備的過程,以下圖為例主要包含以下步驟。
  1. 從RC開始,尋找設備和橋,發現橋以後設置下一級Bus,繼續遞歸發現下一級PCI設備子樹。
  2. 先從Bridge A開始,嘗試讀取配置空間的Vendor ID,看看設備是否存在而且隻是有一個Function。如果不存在就繼續嘗試Device1-31 Function 0。
  3. 下圖的情況A的header type是01h表明這是一個Bridge,Multifunction Bit7是0表示這是一個single function.
  4. 設置Bridge A 的 Primary Bus Number Register = 0 Secondary Bus Number Register = 1 Subordinate Bus Number Register = 255。這樣接在這個bridge下面的總線是bus1,最大的總線是255。
  5. 繼續深度優先搜索,在探索bus0上的其它設備之前,我們先要去探索bus1上的設備樹。
  6. 讀取B1D0F0 Vendor ID和Header Type也就是下圖的C,我們同樣也能知道它是一個Bridge而且是單功能的。
  7. 設置Bridge C的配置空間Primary Bus Number Register = 1 Secondary Bus Number Register = 2 Subordinate Bus Number Register = 255。
  8. 嘗試讀取B2D0F0的Vendor ID也就是下圖的D,同樣我們可以知道它是一個單功能的橋設備。
  9. 設置D的配置空間的寄存器Primary Bus Number Register = 2 Secondary Bus Number Register = 2 Subordinate Bus Number Register = 255。
  10. 讀取B3D0F0的Vendor Id和Header Type進而確認 它是一個設備而且是多Function。
  11. 嘗試遍歷所有的8個Function,可以發現一共存在2個Function 而且都是Endpoint。
  12. 繼續嘗試遍歷bus3下面的所有的Device1-31,這次應該沒有發現任何其他的Function。
  13. 更新Bridge D真正的Subordinate Bus Number Register = 3,然後回到上一級(bus2)繼續遍歷虛招有效的Function,在下圖的例子中我們會找到Bridge E B2D1F0。
  14. 同樣讀取Vendor ID和Header Type表面 E是一個單功能的橋設備。
  15. 設置E的 Primary Bus Number Register = 2 Secondary Bus Number Register = 4 Subordinate Bus Number Register = 255。
  16. 繼續深度優先遍歷讀取B4D0F0的Vendor ID以及Header Type,表明它是一個單功能的設備。
  17. 嘗試遍歷bus4 device 1-31,下圖中找不到其他的功能設備。
  18. 這時已經到瞭樹的底部,接下來更新上層Bridge E的Subordinate Bus Number Register = 4。然後回到上一級總線bus2,嘗試讀取device2-31,因為下圖沒有實現,所以在bus2上找不到其他的設備。
  19. 更新上一級總線也就是C的真正的Subordinate Bus Number Register = 4,然後嘗試讀取Device1-31的其它Function,因為沒有實現,所以找不到其它的Function。
  20. 繼續向上更新bus1的上一級Bridge也就是A,它的真正的Subordinate Bus Number Register = 4,回朔到上一級總線Bus0,繼續讀取下一個設備B0D1F0(也就是B)的Vendor ID和Header Type,接下來的就是重復A的過程。

除瞭配置bus,枚舉過程中還會通過讀取bar記錄所有MMIO和IO的需求情況,然後設置對應的bar以及必要的Capabilities。

Refer:

1. PCI Express Technology 3.0

2. PCI-SIG – PCI Special Interest Group

3. PCIe掃盲系列博文

赞(0)