PCIE配置和地址空間
來源:https://www.jianshu.com/p/574e9a2cbc4e
每個PCIe裝置,有這麼一段空間,Host軟體可以讀取它獲得該裝置的一些資訊,也可以通過它來配置該裝置,這段空間就叫做PCIe的配置空間。不同於每個裝置的其它空間,PCIe裝置的配置空間是協議規定好的,哪個地方放什麼內容,都是有定義的。PCI或者PCI-X時代就有配置空間的概念,那時的配置空間如下:
圖6.1
整個配置空間就是一系列暫存器的集合,其中Type 0是Endpoint的配置,Type 1是Bridge(PCIe時代就是Switch)的配置,都由兩部分組成:64 Bytes的Header+192Bytes的Capability結構,後者是裝置告訴Host它有多牛逼,都會什麼絕活。
進入PCIe時代,PCIe能耐更大,192 Bytes不足以羅列它的絕活。為了保持後向相容,又要不把絕活落下,怎麼辦?很簡單,我擴充套件後者的空間,整個配置空間由256 Bytes擴充套件成4KB,前面256 Bytes保持不變:
圖6.2
PCIe有什麼能耐(Capability)我們不看,我們先挑軟柿子捏,先看看只佔64 Bytes的Configuration Header。
圖6.3
像Device ID,Vendor ID,Class Code和Revision ID,是隻讀暫存器,PCIe裝置通過這些暫存器告訴Host軟體,這是哪個廠家的裝置、裝置ID是多少、以及是什麼型別的(網路卡?顯示卡?橋?)裝置。
其它的我們暫時不看,我們看看重要的BAR(Base Address Register)。
對Endpoint Configuration(Type 0),提供了最多6個BAR,而對Switch(Type 1)來說,只有2個。BAR是幹什麼用的?
每個PCIe裝置,都有自己的內部空間,這部分空間如果開放給Host(軟體或者CPU)訪問,那麼Host怎樣才能往這部分空間寫入資料,或者讀資料呢?
我們知道,CPU只能直接訪問Host記憶體(Memory)空間(或者IO空間,我們不考慮),不對PCIe等外設直接操作。怎麼辦?記得皇帝身邊那個有根的太監嗎?Root Complex,RC。RC可以為CPU分憂。
解決辦法是:CPU如果想訪問某個裝置的空間,由於它不能(或者不屑)親自跟那些PCIe外設打交道,因此叫太監RC去辦。比如,如果CPU想讀PCIe外設的資料,先叫RC通過TLP把資料從PCIe外設讀到Host記憶體,然後CPU從Host記憶體讀資料;如果CPU要往外設寫資料,則先把資料在記憶體中準備好,然後叫RC通過TLP寫入到PCIe裝置。完美!
圖6.4
上圖例子中,最左邊虛線的表示CPU要讀Endpoint A的資料,RC則通過TLP(經歷Switch)資料互動獲得資料,並把它寫入到系統記憶體中,然後CPU從記憶體中讀取資料(紫色箭頭所示),從而CPU間接完成對PCIe裝置資料的讀取。
具體實現就是上電的時候,系統把PCIe裝置開放的空間(系統軟體可見)對映到記憶體空間,CPU要訪問該PCIe裝置空間,只需訪問對應的記憶體空間。RC檢查該記憶體地址,如果發現該記憶體空間地址是某個PCIe裝置空間的對映,就會觸發其產生TLP,去訪問對應的PCIe裝置,讀取或者寫入PCIe裝置。
一個PCIe裝置,可能有若干個內部空間(屬性可能不一樣,比如有些可預讀,有些不可預讀)需要對映到記憶體空間,裝置出廠時,這些空間的大小和屬性都寫在Configuration BAR暫存器裡面,然後上電後,系統軟體讀取這些BAR,分別為其分配對應的系統記憶體空間,並把相應的記憶體基地址寫回到BAR。(BAR的地址其實是PCI匯流排域的地址,CPU訪問的是儲存器域的地址,CPU訪問PCIe裝置時,需要把匯流排域地址轉換成儲存器域的地址。)
圖6.5
如上圖例子,一個Native PCIe Endpoint,只支援Memory Map,它有兩個不同屬性的內部空間要開放給系統軟體,因此,它可以分別對映到系統記憶體空間的兩個地方;還有一個Legacy Endpoint,它既支援Memory Map,還支援IO Map,它也有兩個不同屬性的內部空間,分別對映到系統記憶體空間和IO空間。
來個例子,看一下一個PCIe裝置,系統軟體是如何為其分配對映空間的。
圖6.6
上電時,系統軟體首先會讀取PCIe裝置的BAR0,得到資料:
圖6.7
然後系統軟體往該BAR0寫入全1,得到:
圖6.8
BAR暫存器有些bit是隻讀的,是PCIe裝置在出廠前就固定好的bit,寫全1進去,如果值保持不變,就說明這些bit是廠家固化好的,這些固化好的bit提供了這塊內部空間的一些資訊:
怎麼解讀?低12沒變,表明該裝置空間大小是4KB(2的12次方),然後低4位表明了該儲存空間的一些屬性(IO對映還是記憶體對映,32bit地址還是64bit地址,能否預取?做過微控制器的人可能知道,有些暫存器只要一讀,資料就會清掉,因此,對這樣的空間,是不能預讀的,因為預讀會改變原來的值),這些都是PCIe裝置在出廠前都設定好的,提供給系統軟體的資訊。
然後系統軟體根據這些資訊,在系統記憶體空間找到這樣一塊地方來對映這4KB的空間,把分配的基地址寫入到BAR0:
圖6.9
從而最終完成了該PCIe空間的對映。一個PCIe裝置可能有若干個內部空間需要開放出來,系統軟體依次讀取BAR1,BAR2。。。,直到BAR5,完成所有內部空間的對映。
上面主要講了Endpoint的BAR,Switch也有兩個BAR,今天不打算講,下節講TLP路由,再回過頭來講。繼續說配置空間。
前面說每個PCIe裝置都有一個配置空間,其實這樣說是不準確的,而是每個PCIe裝置至少有一個配置空間。一個PCIe裝置,它可能具有多個功能(function),比如既能當硬碟,還能當網路卡。每個功能對應一個配置空間。
在一個PCIe拓撲結構裡,一條匯流排下面可以掛幾個裝置,而每個裝置可以具有幾個功能,如下所示:
圖6.10
因此,在整個PCIe系統中,只要知道了Bus+Device+Function,就能找到對應的Function。定址基本單元是功能(function),它的ID就由Bus+Device+Function組成 (BDF)。一個PCIe系統,可以最多有256條Bus,每條Bus上可以掛最多32個Device,而每個Device最多又能實現8個Function,而每個Function對應著4KB的配置空間。上電的時候,這些配置空間都是需要對映到Host的記憶體空間,因此,需要佔用記憶體空間是:256*32*8*4KB =256MB。在這個動輒4GB、8GB記憶體的時代,256MB算不了什麼。
系統軟體是如何讀取Configuration空間呢?不能通過BAR中的地址,為什麼?別忘了BAR是在Configuration中的,你首先要讀取Configuration,才能得到BAR。前面不是系統為所有可能的Configuration預留了256MB記憶體空間嗎?系統軟體想訪問哪個Configuration,只需指定相應Function對應的記憶體空間地址,RC發現這個地址是Configuration對映空間,就會產生相應的Configuration Read TLP去獲得相應Function的Configuration。
再回想一下前面介紹的Configuration Read TLP的Header格式:
圖6.11
Bus Number + Device + Function就唯一決定了目標裝置; Ext Reg Number + Register Number相當於配置空間的偏移。找到了裝置,然後指定了配置空間的偏移,就能找到具體想訪問的配置空間的某個位置。
結束前,強調一下,只有RC才能發起Configuration的訪問請求,其他裝置是不允許對別的裝置進行Configuration讀寫的。
作者:idorax
連結:https://www.jianshu.com/p/574e9a2cbc4e
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
相關文章
- 環境變數和地址空間變數
- [Linux]程序地址空間Linux
- 2、儲存容量和儲存地址空間的轉換
- MySQL InnoDB Undo表空間配置MySql
- spring cloud 配置中心git和本地地址配置SpringCloudGit
- 國產處理器龍芯地址空間詳解
- MySQL InnoDB臨時表空間配置MySql
- 坑系列 — 時間和空間的平衡
- iis 配置中,IP地址和域限制
- IPv4 地址耗盡,回收 E 類空間是否有意義?
- oracle建立臨時表空間和資料表空間以及刪除Oracle
- 臨時表空間和回滾表空間使用率查詢
- 晨雲互聯提供免費PHP空間,地址:www.cfvy.cnPHP
- Linux程式上下文和中斷上下文核心空間和使用者空間Linux
- 時間複雜度和空間複雜度時間複雜度
- Python作用域和名稱空間Python
- 硬碟空間的管理和分割槽硬碟
- 16、表空間 建立表空間
- 使用p名稱空間和c名稱空間的XML快捷方式XML
- RHEL8&CentOS8配置IP地址和DNSCentOSDNS
- MySQL空間最佳化(空間清理)MySql
- MySQL InnoDB系統表空間資料檔案配置MySql
- Oracle move和shrink釋放高水位空間Oracle
- oracle 建立表空間和使用者Oracle
- 內聯和巢狀名稱空間巢狀
- Oracle建立表空間和使用者Oracle
- 4.2.1.7 規劃 SYSTEM 和 SYSAUX 表空間UX
- 永久代和元空間的變化
- Linux 磁碟掛載和swap空間管理Linux
- PCIe
- webpack打包地址配置Web
- 配置sqlalchemy的地址SQL
- 配置Dart SDK地址Dart
- UNDO表空間空間回收及切換
- 時間複雜度O(n)和空間複雜度時間複雜度
- 當使用者無限制使用表空間配額且表空間有足夠空間時出現超出表空間的空間限額
- C和C++中的名字空間和作用域C++
- 時間和空間的完美統一!阿里雲時空資料庫正式商業化阿里資料庫