一、概述
CPU如何訪問PCIe配置空間;
CPU能夠通過寄存器訪問配置空間,為什么還需要映射PCIe配置空間;
如何掃描PCIe樹并且為PCIe分配ID;
如何將pcie域地址映射到存儲(chǔ)器域地址空間。
通過本篇文章將對(duì)問題1、2、3做出解答。
二、統(tǒng)一編址于獨(dú)立編址
CPU編址是程序指令與物理地址線建立鏈接的方式,在CPU內(nèi)部有專門的地址集合,編址過程是由CPU體系架構(gòu)所決定的,參考示意圖如圖 1所示(僅僅代表示意圖,講解一種邏輯結(jié)構(gòu),不代表實(shí)際電路)。CPU編址時(shí)就已經(jīng)指定了0x8000_0000~0xFFFF_FFFF這個(gè)地址空間為連接到圖中內(nèi)存的地址線,內(nèi)存如何連接到CPU需要當(dāng)參考CPU的datasheet,當(dāng)CPU程序指令對(duì)0x8000_0000這個(gè)物理地址地址發(fā)起訪問時(shí),等價(jià)于是在訪問圖中2G內(nèi)存的首地址。
圖1
內(nèi)存通過CPU地址總線來尋址定位,然后通過CPU數(shù)據(jù)總線讀寫數(shù)據(jù)。CPU的地址總線位數(shù)是CPU設(shè)計(jì)時(shí)確定,因此一款CPU所能尋址的地址范圍是一定的,而內(nèi)存是需要占用CPU的尋址空間的,內(nèi)存與CPU采用總線直接連接。
IO指的是與CPU連接的各種外設(shè),CPU訪問各種外設(shè)有兩種方式:一種是類似于訪問內(nèi)存的方式,即把外設(shè)的寄存器當(dāng)成內(nèi)存地址讀寫,從文可以以訪問內(nèi)存方式操作外設(shè)寄存器。這時(shí),IO與內(nèi)存統(tǒng)一編址,IO地址與內(nèi)存地址在同一個(gè)地址空間下,這種編址方式叫做IO與內(nèi)存統(tǒng)一編址。
另外一種編址方式是IO地址與內(nèi)存地址分開獨(dú)立編址,這種編址方式叫做獨(dú)立編址,此時(shí),CPU訪問外設(shè)寄存器需要通過CPU特定的指令去訪問外設(shè)寄存器,而不能通過地址直接訪問外設(shè)寄存器。常見的ARM、PowerPc、MIPS架構(gòu)都是采用統(tǒng)一編址,X86架構(gòu)采用獨(dú)立編址。
三、訪問PCIe配置空間256bytes
PCI總線規(guī)定訪問配置空間總線事務(wù),使用ID號(hào)進(jìn)行尋址。PCI設(shè)備ID號(hào)由總線號(hào)(Bus Number)、設(shè)備號(hào)(Device Number)和功能號(hào)(Function Number)。其中總線號(hào)在HOST主橋遍歷PCI總線樹時(shí)確定,在一顆PCI總線樹上,總線號(hào)由系統(tǒng)軟件決定,通常與HOST主橋直接相連接的PCI總線編號(hào)為0,系統(tǒng)軟件使用DFS(Depth-First Search)算法掃描PCI總線樹上的所有PCI總線,并依次編號(hào)。
一條PCI總線的設(shè)備號(hào)由PCI設(shè)備的IDSEL信號(hào)與PCI總線地址線的連接關(guān)系確定,功能號(hào)與PCI設(shè)備的具體設(shè)計(jì)有關(guān)。一個(gè)PCIe系統(tǒng)最多有256條Bus,每條Bus上最多可以掛在32個(gè)設(shè)備,每個(gè)PCIe設(shè)備最多有8個(gè)功能設(shè)備。
在XX處理器中的HOST主橋中,與PCIE設(shè)備配置相關(guān)的寄存器由CFG_ADDR、CFG_DATA等組成。系統(tǒng)軟件使用CFG_ADDR(CFG_ADDR寄存器結(jié)構(gòu)如圖 2所示)和CFG_DATA寄存器訪問PCIe設(shè)備的配置空間,這些寄存器都是采取同一編址(所有內(nèi)存寄存器都使用存儲(chǔ)器映射方式進(jìn)行尋址)。
當(dāng)處理器訪問PCIe配置空間時(shí),首先需要在CFG_ADD寄存器中設(shè)置這個(gè)PCIe設(shè)備對(duì)應(yīng)的總線號(hào)、設(shè)備號(hào)、功能號(hào)和寄存器偏移,然后使能Enable位,之后當(dāng)處理器對(duì)CFG_DATA讀寫訪問時(shí),HOST主橋?qū)⑦@個(gè)存儲(chǔ)器讀寫訪問轉(zhuǎn)換成PCIe配置讀寫請(qǐng)求,并且發(fā)送到PCIe總線上。如果Enable位沒有使能,那么CPU對(duì)寄存器的訪問也就是一個(gè)普通IO的訪問,而不能讓HOST轉(zhuǎn)換成總線請(qǐng)求訪問,訪問PCIe配置空間時(shí)按照PCIe總線標(biāo)準(zhǔn)配置TLP請(qǐng)求,CFG_DATA是讀取的數(shù)據(jù)或者待寫入的數(shù)據(jù)。
圖2
31位:Enable位,為1時(shí),對(duì)CFG_DATA讀寫才能轉(zhuǎn)換成PCIe總線配置請(qǐng)求。
30~24位:保留。
23~16位:總線號(hào),最多=256個(gè)。
15~11位:設(shè)備號(hào),最多=32個(gè)。
10~8位:功能號(hào),最多=8個(gè)。
7~2位:寄存器偏移,最多訪問寄存器=64個(gè)地址,這里一個(gè)地址是DW,那么能干訪問的PCIe配置空間大小為64*4=256Byte,所以訪問PCIe配置空間都是以4字節(jié)對(duì)齊訪問的。
走到這里很多讀者可能就會(huì)有這樣的疑問,既然CPU能夠直接通過寄存器訪問配置空間,為啥還會(huì)出現(xiàn)配置空間在存儲(chǔ)域地址的映射這一說法呢?下面給出詳細(xì)解答。
訪問PCIe配置空間寄存器的方法需要追溯到原始的PCI規(guī)范。為了發(fā)起PCI總線配置周期,Intel(Intel是PCIe龍頭老大,最新的PCIe的規(guī)范總是它最先嘗試的)實(shí)現(xiàn)的PCI規(guī)范使用IO空間的CF8h和CFCh來分別作為索引和數(shù)據(jù)寄存器,這種方法可以訪問所有PCI設(shè)備的255 bytes配置寄存器。Intel Chipsets目前仍然支持這種訪PCI配置空間的方法。
PCIe規(guī)范在PCI規(guī)范的基礎(chǔ)上,將配置空間擴(kuò)展到4K bytes,至于為什么擴(kuò)展到4K,具體可以參考PCIe規(guī)范,這些配置CFG_ADDR和CFG_DATA寄存器方法仍然可以訪問所有PCIe設(shè)備配置空間的頭255 bytes,但是該方法訪問不了剩下的(255B~4K)配置空間。怎么辦呢?Intel外一種PCIe配置空間訪問方法。Intel Chipset通過將配置空間映射到內(nèi)存地址空間,PCIe配置空間可以像對(duì)映射范圍內(nèi)的內(nèi)存進(jìn)行read/write來訪問了。這種映射是由北橋芯片來完成的,但是不同芯片的映射方式也是不同的。目前我查看了ARM芯片的datasheet,確實(shí)是這樣的方式。
PCIe規(guī)范為每個(gè)PCIe設(shè)備添加了更多的配置寄存器,空間為4K,盡管CFG_ADDR和CFG_DATA寄存器方法仍然能夠訪問lower 255 bytes,但是必須提供另外一種方法來訪問剩下的(255B~4K)range寄存器。Intel的解決方案是使用了預(yù)留256MB內(nèi)存地址空間,對(duì)這段內(nèi)存的任何訪問都會(huì)發(fā)起PCIe 配置cycle。
由于4K的配置空間是directly mapped to memory的,那么PCIe規(guī)范必須保證所有的PCIe設(shè)備的配置空間占用不同的內(nèi)存地址,按照PCIe規(guī)范,支持最多256個(gè)bus,每個(gè)Bus支持最多32個(gè)PCIe devices,每個(gè)device支持最多8個(gè)function,也就是說:占用內(nèi)存的最大值為:256 * 32 * 8 * 4K = 256MB。圖 3是ARM Cortex-A9 datasheet內(nèi)存地址分配局部圖。被PCIe配置空間占用的256M內(nèi)存空間會(huì)屏蔽掉DRAM使用該段內(nèi)存區(qū),這些地址都由CPU出廠時(shí)已經(jīng)固化好了。
圖3
四、PCIe配置空間的內(nèi)存映射對(duì)32bit系統(tǒng)的影響
由于PCIe配置空間占用了256M內(nèi)存空間,而且該被占用空間對(duì)DRAM來說是不可用的,這意味著256M空間消失于系統(tǒng)內(nèi)存,這在32bit系統(tǒng)中更為明顯。比如,在32 bit winxp中(作者目前電腦還是用的XP系統(tǒng),電腦用了七八年了),理論上可以訪問到的內(nèi)存是4G,如果4G空間都被DRAM給占用,由于PCIe的存在,被PCIe占用的那部分內(nèi)存空間對(duì)OS來說是不可用的,莫名的消失了最多256M內(nèi)存,其實(shí)還有其他外設(shè)寄存器需要映射到內(nèi)存,如果是獨(dú)立編址就不存在寄存器占用內(nèi)存。
所以在XP系統(tǒng)中實(shí)際能夠訪問DRAM空間最大值為3.2G。64位CPU尋址不存在這個(gè)情況,個(gè)地址目前來說應(yīng)該用不完,這里讀者需要注意的是CPU有32和64位尋址方式,同樣操作系統(tǒng)也有32和64位之分,在Linux系統(tǒng)中主要體現(xiàn)在庫文件上。
有些CPU沒有直接指定PCIe配置空間的地址范圍,需要讀取某個(gè)寄存器的值BaseAddr,這個(gè)值就說PCIe配置寄存器在內(nèi)存區(qū)域映射的基地址。訪問PCIe設(shè)備配置空間時(shí)候需要手動(dòng)計(jì)算訪問PCIe配置空間的地址。計(jì)算發(fā)放如下:
SIZE_PER_FUNC = 4K = 1000h
SIZE_PER_DEVICE = 4K * 8 = 8000h
SIZE_PER_BUS = 4K *8* 32 = 100000h
訪問總線號(hào)為busNo,設(shè)備號(hào)為DevNo,功能號(hào)為funcNo的offset寄存器的計(jì)算公式是:
Memory Address = BaseAddr+ busNo * SIZE_PER_BUS+ devNo * SIZE_PER_DEVICE+ funcNo * SIZE_PER_FUNC+ offset
訪問PCIe配置空間就需要通過總線號(hào)、設(shè)備號(hào)、功能號(hào)、寄存器偏移進(jìn)行轉(zhuǎn)換成內(nèi)存地址。轉(zhuǎn)換函數(shù)如圖 2所示。
圖 4
問題4和5在下篇文章中講解,介于作者實(shí)力有限。如有錯(cuò)誤,望讀者給出寶貴的意見。
-
cpu
+關(guān)注
關(guān)注
68文章
10863瀏覽量
211781 -
PCIe
+關(guān)注
關(guān)注
15文章
1239瀏覽量
82658
原文標(biāo)題:從CPU角度理解PCIe
文章出處:【微信號(hào):SSDFans,微信公眾號(hào):SSDFans】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論