思考:
1、 SOC一上電,只有一個(gè)核啟動(dòng),還是所有核都啟動(dòng)?
2、如果SOC一上電,如果只有一個(gè)核啟動(dòng),那么從核啟動(dòng)的時(shí)候,從核的入口是哪里?
3、啥是cold boot?啥時(shí)warm boot? 在哪些場(chǎng)景下會(huì)使用warm boot?
4、啥是cold reset/warm reset/primary boot/senondary boot?
說明:
1、本文以為armv8-aarch64、armv9為例、TF-A代碼為例,不討論其它硬件架構(gòu)和固件軟件中的設(shè)計(jì)。
2、重點(diǎn)講述cold reset/warm reset/primary boot/senondary boot之間的流程和概念。
1、基礎(chǔ)概念
請(qǐng)先自行理解以下4個(gè)概念:
cold boot
warm boot
Primary boot
Secondary boot
另外還兩種配置:
你的reset地址是可編程的,則會(huì)配置?PROGRAMMABLE_RESET_ADDRESS=1,與之對(duì)立的則是你的reset地址是不可編程的。
你在SOC啟動(dòng)的時(shí)候,首先只啟動(dòng)一個(gè)core,則會(huì)配置?COLD_BOOT_SINGLE_CPU=1,與之對(duì)立的則是你的SOC啟動(dòng)的時(shí)候,所有core都上電了。
2、啟動(dòng)流程
我們就假定 reset地址是可編程的、SOC啟動(dòng)的時(shí)候只啟動(dòng)一個(gè)core,來(lái)講解我們的boot流程:
(1)、SOC一上電,SOC給ARM Core的signal configuration會(huì)改變RVBAREL3,這里一般就是就是bootrom的首地址。即CPU一上電,Primary core的PC指向的就是RVBAREL3的地址,機(jī)器就開始啟動(dòng)了。
(2)、當(dāng)需要Secondary Core啟動(dòng)的時(shí)候,例如會(huì)走PSCI協(xié)議,【主核】進(jìn)入ATF會(huì)將bl31warmentrypoint(或平臺(tái)自定義的地址)寫入到SOC寄存器,改變r(jià)eset地址(改變RVBAREL3的值),然后此時(shí)SOC的PMIC給Secondary Core上電,此時(shí)Secondary Core也就發(fā)生了cold reset,PC從RVBAREL3(bl31warmentrypoint或平臺(tái)自定義函數(shù))處開始執(zhí)行.
總結(jié)(針對(duì)本文示例情況:reset地址是可編程的、cold boot的時(shí)候只啟動(dòng)一個(gè)cpu):
開機(jī)一上電只有Primary Core再跑,從RVBAR_EL3處開始跑,屬于cold boot
從核啟動(dòng)時(shí),會(huì)修改reset的值,影響到RVBAR_EL3的值,然后給從核上電,此時(shí)屬于Secondary boot,仍然是cold boot.
一般會(huì)將bl31warmentrypoint設(shè)置為reset地址,即Secondary Core的啟動(dòng)地址;
這個(gè)示例中沒有用到warm boot
3、ATF(TF-A)代碼的剖析
以BL1代碼為例分析,該代碼適配支持cold reset/warm reset/primary boot/senondary boot等諸多場(chǎng)景。
如果reset是可編程的,?PROGRAMMABLE_RESET_ADDRESS=1, 則?_warm_boot_mailbox=0,則下面這段代碼不會(huì)被編譯,無(wú)論cold boot還是warm boot都不會(huì)走?_warm_boot_mailbox。
如果reset是不可編程的,?PROGRAMMABLE_RESET_ADDRESS=0, 則?_warm_boot_mailbox=1,則下面這段代碼會(huì)被編譯,但cold boot走?do_cold_boot流程,warm boot需要走?br x0流程
.if \_warm_boot_mailbox
/* -------------------------------------------------------------
* This code will be executed for both warm and cold resets.
* Now is the time to distinguish between the two.
* Query the platform entrypoint address and if it is not zero
* then it means it is a warm boot so jump to this address.
* -------------------------------------------------------------
*/
bl plat_get_my_entrypoint
cbz x0, do_cold_boot
br x0
do_cold_boot:
.endif /* _warm_boot_mailbox */
如果SOC啟動(dòng)的時(shí)候只啟動(dòng)一個(gè)core,?COLD_BOOT_SINGLE_CPU=1,?_secondary_cold_boot=0,則下面代碼不被編譯, 則無(wú)論主核還是從核都不需要走?_secondary_cold_boot流程
如果SOC啟動(dòng)的時(shí)候啟動(dòng)多個(gè)core,?COLD_BOOT_SINGLE_CPU=0,?_secondary_cold_boot=1, 則下面代碼會(huì)被編譯,則主核走?do_primary_cold_boot流程, 從核需要走?plat_secondary_cold_boot_setup流程
.if \_secondary_cold_boot
/* -------------------------------------------------------------
* Check if this is a primary or secondary CPU cold boot.
* The primary CPU will set up the platform while the
* secondaries are placed in a platform-specific state until the
* primary CPU performs the necessary actions to bring them out
* of that state and allows entry into the OS.
* -------------------------------------------------------------
*/
bl plat_is_my_cpu_primary
cbnz w0, do_primary_cold_boot
/* This is a cold boot on a secondary CPU */
bl plat_secondary_cold_boot_setup
/* plat_secondary_cold_boot_setup() is not supposed to return */
bl el3_panic
do_primary_cold_boot:
根據(jù)以上的代碼規(guī)則,這里也畫了兩張圖:(1)、BL2 at EL3的場(chǎng)景
(2)、BL2 at S-EL1的場(chǎng)景
5、軟件如何判斷當(dāng)前是cold reset/warm reset/primary boot/senondary boot
TF-A中定義了多核的啟動(dòng)框架,如上一節(jié)框圖所示,在啟動(dòng)的過程中會(huì)進(jìn)行一些判斷,是cold reset還是warm reset,是primary boot還是secondary boot?那么代碼中是怎么知道這些狀態(tài)的呢?
5.1 cold reset和warm reset
這種判斷方法由平臺(tái)實(shí)現(xiàn),其實(shí)就是讀取mailbox的值。在第一個(gè)核cold boot時(shí),會(huì)寫mailbox內(nèi)存(magic,entrypoint...)在第二個(gè)核啟動(dòng)時(shí)、或第一個(gè)核再次啟動(dòng)時(shí)(有可能是resume喚醒時(shí)),會(huì)讀取mailbox內(nèi)存,如果讀取到了符合期望的magic的值,則走warm流程,否則走cold流程。注意這里所說的warm流程,只是軟件上的warm流程,并非說當(dāng)前是warm reset。
5.2 primary boot和secondary boot
這種判斷方法由平臺(tái)實(shí)現(xiàn),看似也很簡(jiǎn)單,一般而言就說讀取mpidr寄存器進(jìn)行判斷。
(trusted-firmware-a/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S)
func plat_is_my_cpu_primary
mrs x0, mpidr_el1
and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
cmp x0, #MVEBU_PRIMARY_CPU
cset w0, eq
ret
endfunc plat_is_my_cpu_primary
6、mailbox的介紹
6.1 mailbox是什么
mailbox就說一塊內(nèi)存,所有的core都能訪問這塊內(nèi)存。第一次啟動(dòng)時(shí),core會(huì)填充mailbox,將其下次resume時(shí)的地址、secondary core的啟動(dòng)地址、warm reset的地址寫入到mailbox內(nèi)存中,這幾個(gè)地址其實(shí)是一個(gè)地址。同時(shí)也會(huì)將這個(gè)地址寫入到SOC PMIC寄存器中,影響到RVBAR_EL3的值。
當(dāng)SOC一上電所有core都啟動(dòng)的這種情況下,主核會(huì)繼續(xù)跑,從核會(huì)在SOC一上電就進(jìn)入wfi狀態(tài)。當(dāng)從核需要繼續(xù)啟動(dòng)時(shí),該core從BL1 BL2 BL31正常流程啟動(dòng)時(shí),會(huì)在BL1、BL2 at EL3、BL31中,強(qiáng)制跳轉(zhuǎn)到mailbox的地址,跳過主核已經(jīng)初始化的部分;
當(dāng)SOC一上電,只有一個(gè)core上電的情況下,主核繼續(xù)跑,從核未上電。當(dāng)從核需要啟動(dòng)時(shí),相當(dāng)于cold reset,從核會(huì)直接從RVBAR_EL3處開始跑,也就是你設(shè)置的entrypoint。
6.2 mailbox的作用
mailbox中定義了entrypoint地址,當(dāng)core從BL1 BL2 BL31正常流程啟動(dòng)時(shí),會(huì)在BL1、BL2 at EL3、BL31中,強(qiáng)制跳轉(zhuǎn)到mailbox的地址,以跳過已初始化的部分。
6.3 mailbox的示例
其實(shí)就是定義了一塊內(nèi)存,主核第一次跑時(shí),會(huì)填充該內(nèi)存。主核第二次跑時(shí)或從和跑時(shí),檢測(cè)該內(nèi)存已經(jīng)填充過了,則走warm啟動(dòng)流程,即強(qiáng)制跳轉(zhuǎn)到mailbox中的address地址。
7、具體場(chǎng)景的總結(jié)
串口中斷中敲擊reboot命令、或系統(tǒng)panic時(shí)導(dǎo)致的機(jī)器重啟?:在一些的SOC廠商設(shè)計(jì)中,應(yīng)該是code reboot。比如在Linux Kernel中敲擊reboot,到底層還是寫的一些寄存器控制pmic(或PMU),直接給cpu下電了。然后再上電,SOC還是會(huì)給Core發(fā)送signal configuration,此時(shí)RVBAR_EL3又會(huì)變成ASIC設(shè)置的值.
Suspend和Resume?:比如我在看ATF中的海思平臺(tái),在ATF的suspend函數(shù),將bl31_warm_entrypoint地址寫入到了SOC PMIC的一個(gè)寄存器中(上電時(shí),該寄存器會(huì)影響的是RVBARADDR信號(hào))。此時(shí)系統(tǒng)深睡的時(shí)候,應(yīng)該是Linux Kernel調(diào)用到ATF,將bl31_warm_entrypoint地址寫入到了pmu/pmic相關(guān)的寄存器中,在下一次reset時(shí),會(huì)影響到signal configuration繼而改變RVBAR_EL3的值。然后還會(huì)給各個(gè)模塊下電(給哪些模塊下電是SOC的設(shè)計(jì)和邏輯),最后再給ARM Core下電, 這就算是深睡了。Resume的時(shí)候,也是有一些SOC的硬件行為,然后再給Core上電,那給Core上電后,一上電執(zhí)行的是哪里?PC還是指向RVBAR_EL3中的地址,當(dāng)然這是我們suspend的時(shí)候更改過的,其實(shí)就是bl31_warm_entrypoint
RMR_EL3?:本文中都沒有提到RMR_EL3。那么RMR_EL3是干啥的呢?這是ARM的一個(gè)feature,怎么用?是你自己的設(shè)計(jì),隨便你。你寫RMR_EL3中的bit,就可以觸發(fā)warm reset. 一般的kernel dump、或者一些工具,就可以主動(dòng)觸發(fā)RMREL3,然后去干一些活. 還有在csdn上看到一篇高通soc的啟動(dòng)流程的博客,他們正常的啟動(dòng)流程中,某一個(gè)鏡像跳轉(zhuǎn)到另外一個(gè)鏡像時(shí),竟然就是寫了一些RMR_EL3,觸發(fā)warm_reset,另外一個(gè)鏡像的地址恰好就是warm reset的跳轉(zhuǎn)地址。
審核編輯:劉清
評(píng)論
查看更多