PCIe掃盲:Memory & IO 地址空間/基地址寄存器詳解/Base & Limit寄存器詳解
轉載:PCIe掃盲:Memory & IO 地址空間/基地址寄存器詳解/Base & Limit寄存器詳解 - 極術社區 - 連接開發者與智能計算生態 (aijishu.com)
Memory & IO 地址空間
早期的PC中,所有的IO設備(除了存儲設備之外的設備)的內部存儲或者寄存器都只能通過IO地址空間進行訪問。但是這種方式局限性很大,而且效率低,于是乎,軟件開發者和硬件廠商都不能忍了……然后一種新的東西就出來了——MMIO。
MMIO,即Memory Mapped IO,也就是說把這些IO設備中的內部存儲和寄存器都映射到統一的存儲地址空間(Memory Address Space)中。
但是,為了兼容一些之前開發的軟件,PCIe仍然支持IO地址空間,只是建議在新開發的軟件中采用MMIO。
注:PCIe Spec中明確指出,IO地址空間只是為了兼容早期的PCI設備(Legacy Device),在新設計中都應當使用MMIO,因為IO地址空間可能會被新版本的PCI Spec所拋棄。
IO地址空間的大小是4GB(32bits),而MMIO則取決于處理器(和操作系統),并且由處理器進行統一分配管理。
如下圖所示,PCIe總線中有兩種MMIO:P-MMIO和NP-MMIO。
P-MMIO,即可預取的MMIO(Prefetchable MMIO);
NP-MMIO,即不可預取的MMIO(Non-Prefetchable MMIO)。其中P-MMIO讀取數據并不會改變數據的值。
注:P-MMIO和NP-MMIO主要是為了兼容早期的PCI設備,因為PCIe請求中明確包含了每次的傳輸的大小(Transfer Size),而PCI并沒有這些信息。
基地址寄存器(BAR)詳解
基地址寄存器(BAR)在配置空間(Configuration Space)中的位置如下圖所示:
其中Type0 Header最多有6個BAR,而Type1 Header最多有兩個BAR。
這就意味著,對于Endpoint來說,最多可以擁有6個不同的地址空間。但是實際應用中基本上不會用到6個,通常1~3個BAR比較常見。
主要注意的是,如果某個設備的BAR沒有被全部使用,則對應的BAR應被硬件全被設置為0,并且告知軟件這些BAR是不可以操作的。
對于被使用的BAR來說,其部分低比特位是不可以被軟件操作的,只有其高比特位才可以被軟件操作。
而這些不可操作的低比特決定了當前BAR支持的操作類型和可申請的地址空間的大小。
一旦BAR的值確定了(Have been programmed),其指定范圍內的當前設備中的內部寄存器(或內部存儲空間)就可以被訪問了。當該設備確認某一個請求(Request)中的地址在自己的BAR的范圍內,便會接受這請求。
下面用幾個簡單的例子來熟悉BAR的機制:
例1. 32-bit Memory Address Space Request
如下圖所示,請求一個4KB的NP-MMIO一般需要以下三個步驟:
Step1:如圖中(1)所示,未初始化的BAR的低比特(11~4)都是0,高比特(31~12)都是不確定的值。
所謂初始化,就是系統(軟件)向整個BAR都寫1,來確定BAR的可操作的最低位是哪一位。
當前可操作的最低位為12,因此當前BAR可申請的(最小)地址空間大小為4KB(2^12)。如果可操作的最低位為20,則該BAR可申請的(最小)地址空間大小為1MB(2^20)。
Step2:完成初始化(寫1操作)之后,軟件便開始讀取BAR的值,來確定每一個BAR對應的地址空間大小和類型。其中操作的類型一般由最低四位所決定,具體如上圖右側部分所示。
Step3:最后一步是,軟件向BAR的高比特寫入地址空間的起始地址(Start Address)。如圖中所示,為0xF9000000。
例2. 64-bit Memory Address Space Request
下面是一個申請64MB P-MMIO地址空間的例子,由于采用的是64-bit的地址,因此需要兩個BAR。具體如下圖所示:
例3. IO Address Space Request
下面是一個申請IO地址空間的例子,如下圖所示:
注:需要特別注意的是,軟件對BAR的檢測與操作(Evaluating)必須是順序執行的,即先BAR0,然后BAR1,……,直到BAR5。當軟件檢測到那些被硬件設置為全0的BAR,則認為這個BAR沒有被使用。
注:無論是PCI還是PCIe,都沒有明確規定,第一個使用的BAR必須是BAR0。事實上,只要設計者原意,完全可以將BAR4作為第一個BAR,并將BAR0~BAR3都設置為不使用。
Base & Limit寄存器詳解
上一篇文章介紹了Type0型配置空間Header中的BAR的作用和用法,但是PCIe中的橋設備(Switch和Root中的P2P)又是如何判斷某一請求(Request)是否屬于自己或者自己的分支下的設備的呢?這實際上是通過Type1型配置空間Header中的Base和Limit寄存器來實現的,這篇文章來進行簡單地介紹一下。
Base和Limit寄存器在Type1 Header中的位置如下圖所示:
Base和Limit寄存器分別確定了其所有分支下設備(The device that live beneath this bridge)的地址的起始和結束地址。根據請求類型的不同,分別對應不同的Limit&Base組合:
· Prefetchable Memory Space(P-MMIO)
· Non- Prefetchable Memory Space(NP-MMIO)
· IO Space(IO)
一旦該橋分支下面的任意設備的BAR發生改變,該橋的Base&Limit寄存器也需要做出對應的改變。
下面以一個簡單的例子,來分析一下:
如上圖所示,連接到Switch的PortB上的PCIe Endpoint分別配置了NP-MMIO、P-MMIO和IO空間。下面來簡單地分析一下PortB的Header中的Base & Limit 寄存器。
P-MMIO Base & Limit
NP-MMIO Base & Limit
需要注意的是,Endpoint的需要的NP-MMIO的大小明明只有4KB,PortB的Header卻給其1MB的空間(最小1MB),也就是說剩余的空間都將會被浪費掉,并且其他的Endpoint都將無法使用這一空間。
IO Base & Limit
注:IO空間可分配的最小值為4KB,最大值則取決于操作系統和BIOS。
Unused Base and Limit Registers
很多情況下,我們并不需要所有的地址空間類型,比如所在某一個Endpoint中沒有使用IO Space。此時,其對應的橋的Header會把Base的地址設置為大于Limit的地址,也就是把地址范圍設置為無效。
一個完整的例子如下圖所示:
NP-MMIO(Non-Prefetchable Memory-Mapped I/O)和P-MMIO(Prefetchable Memory-Mapped I/O)以及IO空間是PCIe(Peripheral Component Interconnect Express)中定義的不同類型的地址空間,用于不同類型的內存訪問:
1. **NP-MMIO(不可預取的內存映射I/O)**:
- 用于那些讀取操作可能會改變設備狀態的設備,例如某些硬件寄存器。
- 通常用于非易失性存儲器或某些特殊硬件的訪問,其中讀取操作可能會有副作用。
- 地址空間可以是32位或64位,取決于系統和設備的支持。
2. **P-MMIO(可預取的內存映射I/O)**:
- 用于那些讀取操作不會改變設備狀態的設備,例如常規的內存訪問。
- 由于讀取操作沒有副作用,因此可以安全地進行預取和緩存。
- 這種類型的地址空間通常用于通用的內存訪問,如DRAM。
3. **IO空間**:
- 傳統上用于訪問IO設備,如硬盤控制器或網絡接口卡的寄存器。
- 與MMIO相比,IO空間通常具有較低的帶寬和更高的延遲。
- PCIe規范中仍然支持IO空間,主要是為了向后兼容舊的PCI設備,但在新設計中推薦使用MMIO。
在實際使用中,系統軟件需要根據設備的特定需求來分配適當的地址空間。例如,如果一個設備需要高速數據傳輸且對數據的預取不會影響其狀態,那么P-MMIO是更好的選擇。相反,如果設備的某些寄存器在讀取時會改變其狀態,那么NP-MMIO或IO空間可能更合適。系統軟件通過配置空間中的基地址寄存器(BAR)來分配和管理這些地址空間 。
總的來說,NP-MMIO、P-MMIO和IO空間在PCIe架構中提供了靈活的尋址選項,以滿足不同設備的特定需求。隨著技術的發展,新設計的設備越來越多地采用MMIO方式,以實現更高效的數據傳輸和更好的系統性能。
浙公網安備 33010602011771號