CPU Reset后,CPU會Reset內部的寄存器(注1),然后會從特定的地址抓取第一條指令并執行,這個特定的地址落在Flash(BIOS ROM)中。關于第一條指令的地址、從哪里獲取、誰來執行,下文做了簡單的介紹。
我是誰 – 指令的地址
1978年,第一代x86處理器8086發布,它是一個16 bit處理器,擁有20 bit Bus,最大可以尋址 1MB (2 ^20 = 1MB),所以其地址需要兩個16 bit寄存器表示,即:的方式表示,由于8086只支持實模式,所以實際地址(PA) = * 0x10 + 。當時的設計人員認為1MB的尋址已經足夠滿足未來的需求,并且是實模式的最大可尋址地址為1MB, 所以在設計時把CPU的第一條指令放在可尋址的最高處,即。
1982年,80286處理器發布,它仍然是一個16 bit 處理器,但擁有24 bit Bus,最大可以尋址16MB(高于1MB的內存需要通過INT 15h, AH=87h訪問),并且引入了保護模式;但CPU執行第一條指令時仍是實模式,CPU第一條指令地址還是。啟用保護模式后,地址可分為邏輯地址和物理地址。CPU Core中執行單元使用的地址為邏輯地址,物理地址是所有內存的地址進行統一編碼后的地址,邏輯地址需要經過轉換成物理地址才可以訪問內存數據(注2),實模式和保護模式的地址組成都為:。1985年,80386處理器發布,它是一個32bit x86處理器,擁有32 bit Bus,最大尋址4GB (2^32),為了保持兼容,CPU執行的第一條指令地址仍為(物理地址),但也可以通過A6#控制設定為(物理地址),無論A6#的是高還是低 CS:IP的值都是F000:FFF0h。當前的Intel CPU不再支持設定第一條指令地址位(物理地址),只支持(物理地址)(注3)。很多同學可能聽過這種說法:CPU第一條指令地址為,這種說法也是正確的(但不建議繼續使用這種說法)),是實模式下的“邏輯地址”,原因如下:引入保護模式后,實模式的地址其實利用了保護模式的設計,表面看起來還是Seg * 0x10+,實際上是 Seg Base + ;CPU Reset后處于實模式,雖然此時CS為F000h,但CS Seg Base的實際值為,那么轉換后的物理地址為 (注4)。當CS被修改后,CS Seg Base地址會變為 CS * 0x10;而由于Flash 被映射到了4G以下,所以后的代碼必須在CS被修改前完成保護模式的初始化。
CPU Reset后的第一條指令:
eax=00000000 esi=00000000 cr0=60000010dr0=00000000
ebx=00000000 edi=00000000 cr2=00000000dr1=00000000
ecx=00000000 ebp=00000000 cr3=00000000dr2=00000000
edx=000306a9 esp=00000000 cr4=00000000dr3=00000000
dr6=ffff0ff0
eip=0000fff0 eflags=00010002 dr7=00000400
idtbase=0000000000000000 idtlimt=0000ffff
qdtbase=0000000000000000 qdtlimt=0000ffff
idtbase=0000000000000000 idtlimt=0000ffffldtar=0082 ldtr=0000
tssbase=0000000000000000 tsslimt=0000fffftssar=008b tr=0000
csbase=ffff0000 cslimt=0000ffff csar=0093 cs=f000
dsbase=00000000 dslimt=0000ffffdsar=0093 ds=0000
ssbase=00000000 sslimt=0000ffffssar=0093 ss=0000
esbase=00000000 eslimt=0000ffffesar=0093 es=0000
fsbase=00000000 fslimt=0000fffffsar=0093 fs=0000
gsbase=00000000 gslimt=0000ffffgsar=0093 gs=0000
實模式下的尋址:
eax=0000c700 esi=0000010d crO=00000012 dr0=00000000
ebx=00000000 edi=000001fb cr2=00000000 drl=00000000
ecx=0000000d ebp=00000000 cr3=da80e000 dr2=00000000
edx=00000133 esp=00000a7e cr4=00000648 dr3=00000000
dr6=ffff0ff0
eip=00009a97 eflags=00010246 dr7=00000400
idtbase=0000000000000000 idtlimt=000003ff
gdtbase=00000000000fe260 qdtlimt=00000060
idtbase=0000000000000000 idtlimt=ffffffff ldtar=cf00ldtr=0000
tssbase=0000000000000000 tsslimt=0000ffff tssar=008btr=0000
csbase=000060c0 cslimt=0000ffff csar=009b cs=060c
dsbase=00000c90 dslimt=0000ffff dsar=0093 ds=00c9
ssbase=00000c90 sslimt=ffffffff ssar=8f93 ss=00c9
esbase=00000c90 eslimt=0000ffff esar=0093 es=00c9
fsbase=00000000 fslimt=ffffffff fsar=8f93 fs=0000
gsbase=000f0000 gslimt=ffffffff gsar=8f93 gs=f000
CPU Reset后,修改CS為E000h,變為
eax=00000000 esi=00000000 cr0=60000010 dr0=00000000
ebx=00000000 edi=00000000 cr2=00000000 drl=00000000
ecx=00000000 ebp=00000000 cr3=00000000 dr2=00000000
edx=000306a9 esp=00000000 cr4=00000000 dr3=00000000
dr6=ffff0ff0
leip=0000fff0eflags=00010002 dr7=00000400
idtbase=0000000000000000 idtlimt=0000ffff
qdtbase=0000000000000000 qdtlimt=0000ffff
idtbase=0000000000000000 idtlimt=0000ffff 1dtar=00821dtr=0000
tssbase=0000000000000000 tsslimt=0000ffff tssar=008btr=0000
csbase=000e0000 cslimt=0000ffff csar=0093 cs=e000
dsbase=00000000 dslimt=0000ffff dsar=0093 ds=0000
ssbase=00000000 sslimt=0000ffff ssar=0093 ss=0000
esbase=00000000 eslimt=0000ffff esar=0093 es=0000
fsbase=00000000 fslimt=0000ffff fsar=0093 fs=0000
gsbase=00000000 gslimt=0000ffff gsar=0093 gs=0000
從哪里來 – 從哪里獲取
當前x86服務器處理器的4G以下的16MB地址,會映射到Flash,具體映射到Flash的哪一區塊由ME/SPS的設定確定(注5)。在ME/SPS的配置工具中,需要設定當前BIOS + ME/SPS鏡像文件的所需的Flash大小,實際使用的Flash大小可以大于鏡像文件,比如實際使用64MB Flash,而設定為32MB大小,4G-16MB ~ 4B -1會映射到Flash 16MB ~ 32MB-1的空間,那么地址會映射到的地方。當前常用的Flash芯片為SPI ROM,為了支持CPU的 In Place(XIP)要求,并能快速的讀取到SPI ROM中的內容,SPI 需要支持/Read-Only訪問模式:映射SPI ROM空間到內存地址,不需要初始化SPI ,不需要通過傳統模式寫入目的地址、觸發讀命令、輪詢狀態、讀取數據的方式讀取內容。下圖為兩種模式的示意圖:
到哪里去 – 誰來執行
CPU Reset后,CPU內部的電路會選擇出一個需要執行第一條指令的Core,被稱為Boot Strap (BSP),其它Core執行一個最小的初始化后,處于一個特殊的等待“喚醒”的掛起狀態,被稱為(AP),BSP和AP可以通過 MSR 1Bh bit 8 BSP 和AP:1 = BSP。
多路系統中每個上的CPU都有一個BSP,所有的BSP都會執行BIOS代碼。 上的BSP又被稱為 BSP (SBSP),其它的稱為Non-SBSP(NBSP)或(PBSP),在BIOS SEC階段結束時,SBSP會繼續往下執行進入PEI階段,而NBSP會進入一個循環等待SBSP通過Pipe傳遞命令執行后續的初始化。
思考
最后留一個問題給大家:為什么CPU Reset后的前兩條指令為NOP?
注:
Warm Reset時,CPU內部屬性的寄存器中的內容不會被Reset到默認值。
如果啟用了分頁,邏輯地址需要先轉換為線性地址,然后轉換為物理地址。
支持TXT功能(DRTM)的CPU,相關功能的代碼會在執行第一條BIOS指令(處獲取)前就被CPU加載執行。
參考IA32 SDM Vol3 Ch9.1.4 :
The first that is and a reset is at . is 16 bytes below the ’s . The the - code must be at this .
The is the 1-MByte of the while in real- mode. The is this as . The CS has two parts: the part and the base part. In real- mode,the base is by the 16-bit 4 bits to the left to a 20-bit base . , reset, the in the CS is with the base is with . The is by the base to the value in the EIP (that is, + FFF0H = )
雖然當前x86處理器只能映射4G以下16MB空間到BIOS ROM邏輯地址轉換為物理地址邏輯地址轉換為物理地址,不代表BIOS所占用的空間只能被限制為16MB。