硬碟是大家都很熟悉的裝置,一路走來,從hdd到ssd,從sata到nvme,作為nvme ssd的前端介面,pcie再次進入我們的視野。作為x86體系關鍵的一環,pcie標準歷經pci,pci-x和pcie,走過近30年時光。其中host發現與查詢裝置的方式卻一脈沿襲,今天我們先來聊一聊pcie裝置在乙個系統中是如何發現與訪問的。
首先我們來看一下在x86系統中,pcie是什麼樣的乙個體系架構。下圖是乙個pcie的拓撲結構示例,pcie協議支援256個bus, 每條bus最多支援32個device,每個device最多支援8個function,所以由bdf(bus,device,function)構成了每個pcie裝置節點的身份證號。
pcie體系架構一般由root complex,switch,endpoint等型別的pcie裝置組成,在root complex和switch中通常會有一些embeded endpoint(這種裝置對外不出pcie介面)。這麼多的裝置,cpu啟動後要怎麼去找到並認出它們呢? host對pcie裝置掃瞄是採用了深度優先演算法,其過程簡要來說是對每乙個可能的分支路徑深入到不能再深入為止,而且每個節點只能訪問一次。我們一般稱這個過程為pcie裝置列舉。列舉過程中host通過配置讀事物包來獲取下游裝置的資訊,通過配置寫事物包對下游裝置進行設定。
第一步,pci host主橋掃瞄bus 0上的裝置(在乙個處理器系統中,一般將root complex中與host bridge相連線的pci匯流排命名為pci bus 0),系統首先會忽略bus 0上的embedded ep等不會掛接pci橋的裝置,主橋發現bridge 1後,將bridge1 下面的pci bus定為 bus 1,系統將初始化bridge 1的配置空間,並將該橋的primary bus number 和 secondary bus number暫存器分別設定成0和1,以表明bridge1 的上游匯流排是0,下游匯流排是1,由於還無法確定bridge1下掛載裝置的具體情況,系統先暫時將subordinate bus number設為0xff。
第二步,系統開始掃瞄bus 1,將會發現bridge 3,並發現這是乙個switch裝置。系統將bridge 3下面的pci bus定為bus 2,並將該橋的primary bus number 和 secondary bus number暫存器分別設定成1和2,和上一步一樣暫時把bridge 3 的subordinate bus number設為0xff。
第三步,系統繼續掃瞄bus 2,將會發現bridge 4。繼續掃瞄,系統會發現bridge下面掛載的nvme ssd裝置,系統將bridge 4下面的pci bus定為bus 3,並將該橋的primary bus number 和 secondary bus number暫存器分別設定成2和3,因為bus3下面掛的是端點裝置(葉子節點),下面不會再有下游匯流排了,因此bridge 4的subordinate bus number的值可以確定為3。
第四步,完成bus 3的掃瞄後,系統返回到bus 2繼續掃瞄,會發現bridge 5。繼續掃瞄,系統會發現下面掛載的nic裝置,系統將bridge 5下面的pci bus設定為bus 4,並將該橋的primary bus number 和 secondary bus number暫存器分別設定成2和4,因為nic同樣是端點裝置,bridge 5的subordinate bus number的值可以確定為4。
第五步,除了bridge 4和bridge 5以外,bus2下面沒有其他裝置了,因此返回到bridge 3,bus 4是找到的掛載在這個bridge下的最後乙個bus號,因此將bridge 3的subordinate bus number設定為4。bridge 3的下游裝置都已經掃瞄完畢,繼續向上返回到bridge 1,同樣將bridge 1的subordinate bus number設定為4。
第六步,系統返回到bus0繼續掃瞄,會發現bridge 2,系統將bridge 2下面的pci bus定為bus 5。並將bridge 2的primary bus number 和 secondary bus number暫存器分別設定成0和5, graphics card也是端點裝置,因此bridge 2 的subordinate bus number的值可以確定為5。
至此,掛在pcie匯流排上的所有裝置都被掃瞄到,列舉過程結束,host通過這一過程獲得了乙個完整的pcie裝置拓撲結構。
系統上電以後,host會自動完成上述的裝置列舉過程。除一些專有系統外,普通系統只會在開機階段進行進行裝置的掃瞄,啟動成功後(列舉過程結束),即使插入乙個pcie裝置,系統也不會再去識別它。
在linux作業系統中,我們可以通過lspci –v -t命令來查詢系統上電階段掃瞄到的pcie裝置,執行結果會以乙個樹的形式列出系統中所有的pcie裝置。如下圖所示,其中黃色方框中的pcie裝置是北京憶芯科技公司(bejing starblaze technology co., ltd.)推出的star1000系列nvme ssd主控晶元,圖中顯示的9d32是starblaze在pci-sig組織的註冊碼,1000是裝置系列號。
star1000裝置的bdf也可以從上圖中找出,其中bus是0x3c,device是0x00,function是0x0,bdf表示為3c:00.0,與之對應的上游埠是00:1d.0。
當然也可以使用lspci –vvv –s 3c:00.0命令來檢視裝置特性,初學者看到下面的列表也就一目了然了。
host在列舉裝置的同時也會對裝置進行配置,每個pcie裝置都會指定一段cpu memory訪問空間,從上面的圖中我們可以看到這個裝置支援兩段訪問空間,一段的大小是1m byte,另一段的大小是256k byte,系統會分別指定它們的基位址。基位址配置完成以後,host就可以通過位址來對pcie memory空間進行訪問了。
pcie memory空間關聯的是pcie裝置物理功能,對於star1000系列晶元而言,物理功能是nvme,memory中存放的是nmve的控制與狀態資訊,對於nmve的控制以及工作狀態的獲取,都需要通過memory訪問來實現。
下面以nvme命令下發為例簡單描述pcie裝置的memory訪問。nvme命令下發的基本操作是1)host寫doorbell暫存器,此時使用pcie memory寫請求。如下圖所示,host發出乙個memory write(mwr)請求,該請求經過switch到達要訪問的nvme ssd裝置。
這個請求會被端點裝置接收並執行2)nvme讀取命令操作。如下圖所示,此時nvme ssd作為請求者,發出乙個memory read(mrd)請求,該請求經過switch到達host,host作為完成者會返回乙個完成事物包(cpld),將訪問結果返回給nvme ssd。
這樣,乙個nvme的命令下發過程就完成了。同樣,nvme的其他操作比如各種佇列操作,命令與完成,資料傳輸都是通過pcie memory訪問的方式進行的,此處不再詳述。
通過上面的描述,相信能夠幫助大家了解pcie的裝置列舉和memory空間訪問。以後會繼續與大家**pcie的其他內容,比如pcie的協議分層,鏈路建立,功耗管理等等。目前pcie協議還正在不斷的快速演進中,2023年發布的pcie gen4標準,每條serdes支援的速率已經達到16gbps,gen5也在加速制定中,其速率會再翻一倍達到32gbps。starblaze會緊跟技術的發展趨勢,提供速率更高,效能更好更穩定的nvme ssd系列產品。
參考:
pcie匯流排與cpci匯流排 PCIE 學習筆記
最近看到了pcie知識點,這裡做了一些總結跟大家分享一下。pcie的由來 上世紀90年代,intel 提出了pci 的概念,並聯合ibm等其他公司成立的pci sig pci special interest group 以制定相應的規範。從pci到pci x,再pcie 1.0,pcie 2.0,...
pcie匯流排與cpci匯流排 PCIE技術概述
ssd的協議標準除了sata,還有乙個更先進的協議標準,就是pcie。pcie匯流排使用了高速差分匯流排,並採用了端到端的連線方式。兩個裝置之間的的傳輸通道,稱為link,由1,2,4,8,16,32個lane組成。lane的數目代表link的傳輸寬度 x1,x2,x4,x8,x16,x32 lan...
PCIe匯流排初識
pcie匯流排 一 pcie匯流排與pci匯流排的區別 pcie匯流排與pci最大的區別在工作原理上,pcie是採用點到點的序列方式進行傳輸的,被稱為 序列pci 由於採用了序列方式傳輸使得其工作頻率可以達到2.5ghz,大大增加了傳輸速率,同時採用全雙工的通訊方式,使得其傳輸速度提高了一倍,每乙個...