最近因為工作需要用到pci設備的BAR內容,之前看了沒深刻印象,這里整理一下。
PCI設備有很好的可配置型和易操作性,這很大方面要歸功於其地址空間的可動態分配的特性。而動態分配地址空間就是依賴於BAR(base address register)實現的。
BAR是PCI配置空間中從0x10 到 0x24的6個register,用來定義PCI需要的配置空間大小以及配置PCI設備占用的地址空間。
每個PCI設備在BAR中描述自己需要占用多少地址空間,bios通過所有設備的這些信息構建一張address map,描述系統中資源的分配情況,然后在合理的將地址空間配置給每個PCI設備。這里主要分為幾個部分描述:
1. PCI設備占用的地址空間大小:
這個是根據PCI設備的需求而不同的,這個映射空間不同於配置空間,一般想網卡等設備占用較大的地址空間,而一些串口等設備占用較少的地址空間,而我們知道X86中地址空間又MEM和IO兩類,因此PCI 的BAR在bit0來表示該設備是映射到memory還是IO,bar的bit0是readonly的,也就是說,設備寄存器是映射到memory還是IO是由設備制造商決定的,其他人無法修改。
下圖是BAR寄存器的結構:
bit0:表示設備寄存器是映射到memory(0)還是IO(1)空間。
bit1: reserved 0
bit2: 在base adress register for Memory 中0表示32位地址空間,1表示64位地址空間。
bit3:在memory BAR中用來表示該設備是否允許prefetch,1表示可以預取,0表示不可以預區。
其余的bit用來表示設備需要占用的地址空間大小。
BAR通過將某些位設置為只讀,且0來表示需要的地址空間大小,比如一個PCI設備需要占用1MB的地址空間,那么這個BAR就需要實現高12bit是可讀寫的,而20-4bit是只讀且位0。地址空間大小的計算方法如下:
a.向BAR寄存器寫全1
b.讀回寄存器里面的值,然后clear 上圖中特殊編碼的值,(IO 中bit0,bit1, memory中bit0-3)。
c.對讀回來的值去反,加一就得到了該設備需要占用的地址內存空間。
BIOS將系統中所有的PCI設備需要的地址空間大小讀出來,然后計算得到一張address map。
bios可以為設備預留大於BAR要求的地址空間,而PCI規范中建議為需要的地址空間少於4KB的設備分配4KB的地址空間。
映射到IO空間的設備每個BAR不能占用大於256byte,在X86系統中IO編址是16位的,此時BAR中的高16bit需要hardware to zero。
2. memory address map構造完成以后需要為設備分配地址空間,此時就是把分配給設備的起始地址寫入BAR寄存器即可。
比如上面位一個設備分配1MB的空間,在0xff000000(4GB-16MB)的位置,那么就把0xff000000寫入BAR即可。
我們發現PCI這種地址自然地要求位設備分配的地址空間要跟BAR定義的大小對齊,因此PCI設備的映射空間始終是跟BAR的大小對齊的。
以上就是一些總結,有些地方可能理解有偏差,沒有畫圖,以后有機會再補上吧~