電源管理入門(mén)-關(guān)機(jī)重啟基礎(chǔ)知識(shí)詳解_第1頁(yè)
電源管理入門(mén)-關(guān)機(jī)重啟基礎(chǔ)知識(shí)詳解_第2頁(yè)
電源管理入門(mén)-關(guān)機(jī)重啟基礎(chǔ)知識(shí)詳解_第3頁(yè)
電源管理入門(mén)-關(guān)機(jī)重啟基礎(chǔ)知識(shí)詳解_第4頁(yè)
電源管理入門(mén)-關(guān)機(jī)重啟基礎(chǔ)知識(shí)詳解_第5頁(yè)
已閱讀5頁(yè),還剩11頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第第頁(yè)電源管理入門(mén)-關(guān)機(jī)重啟基礎(chǔ)知識(shí)詳解當(dāng)我們接觸(電源管理)的時(shí)候,最簡(jiǎn)單的流程就是

關(guān)機(jī)重啟

,但是仔細(xì)分析其涉及的所有源代碼就會(huì)發(fā)現(xiàn),關(guān)機(jī)重啟雖然簡(jiǎn)單,但是“

麻雀雖小,五臟俱全

”,涉及到的軟件模塊非常的多,涉及的流程:(Linux)應(yīng)用(busybox)-》Linux內(nèi)核-》BL31-》SCP-》(PMIC)/CRU等(硬件)。所以是一個(gè)入門(mén)學(xué)習(xí),特別是還沒(méi)接觸過(guò)Linux內(nèi)核代碼的好機(jī)會(huì),下面進(jìn)入代碼的海洋遨游,

超級(jí)干貨

!

1.關(guān)機(jī)重啟軟件流程框圖

在Linux系統(tǒng)上的處理分為**用戶(hù)態(tài)**空間、**內(nèi)核**空間、**ATF**、**SCP**四個(gè)階段(ATF是(ARM)獨(dú)有的,SCP在復(fù)雜SoC上才有應(yīng)用)來(lái)處理:

BL31中smc異常觸發(fā)流程圖

執(zhí)行SMC指令后會(huì)觸發(fā)異常,進(jìn)入ATF的BL31中繼續(xù)執(zhí)行:

在Linux側(cè)調(diào)用smc異常之后,會(huì)根據(jù)中斷向量表觸發(fā)cpu的同步異常sync_exception_aarch64/32

然后跳轉(zhuǎn)執(zhí)行到handle_sync_exception->smc_handler64/32中

根據(jù)_RT_SVC_DESCS_START_+RT_SVC_DESC_HANDLE的位置,跳轉(zhuǎn)執(zhí)行rt_svc_desc_t結(jié)構(gòu)體保存的服務(wù)std_svc_smc_handler

執(zhí)行psci相關(guān)處理,找到psci_system_off和psci_system_rese處理函數(shù)。ATF直接處理如果是關(guān)機(jī)就執(zhí)行halt指令,重啟則通過(guò)設(shè)置gpio,或者轉(zhuǎn)送給SCP處理。

最后跳轉(zhuǎn)到el3_exit返回Linux側(cè)。

SMC異常觸發(fā)執(zhí)行流程:

(32*4)

//這個(gè).應(yīng)該是當(dāng)前位置-段的開(kāi)頭地址如果大于32條指令

.error"Vectorexceeds

32instructions"

//向量超過(guò)32條指令

.endif4.3

runtime服務(wù)程序初始化

bl31_entrypoint入口向下執(zhí)行首先是bl31_setup,然后是bl31_main

void

bl31_setup(u_register_targ0,u_register_targ1,u_register_targ2,

u_register_targ3)

{

/*Pe(rf)ormearly

platform-specificsetup*/

bl31_early_platform_setup2(arg0,arg1,arg2,arg3);

/*Performlate

platform-specificsetup*/

bl31_plat_arch_setup();bl31_main()函數(shù):

void

bl31_main(void)

{

NOTICE("BL31:%s",

version_string);

NOTICE("BL31:%s",

build_message);

bl31_platform_setup();

//通用和安全(時(shí)鐘)初始化,其他(芯片)相關(guān)功能初始化

bl31_lib_init();

//空函數(shù)

INFO("BL31:Initializing

runtimeservices");

runtime_svc_init();

//重點(diǎn)下面展開(kāi)分析

if(bl32_init){

INFO("BL31:

InitializingBL32");

(*bl32_init)();

}

bl31_prepare_next_image_entry();

//加載下一階段的入口地址

console_flush();

//控制臺(tái)刷新

bl31_plat_runtime_setup();

//空函數(shù)

}runtime_svc_init()函數(shù)

//注冊(cè)smc指令相關(guān)的服務(wù)

voidruntime_svc_init(void)

{

intrc=0;

unsignedintindex,start_idx,

end_idx;

/*Assertthenumberof

descriptorsdetectedarelessthan(maxim)umindices*/

//這句話表明

RT_SVC_DECS_NUM時(shí)當(dāng)前加載的服務(wù)數(shù)量

assert((RT_SVC_DESCS_END>=

RT_SVC_DESCS_START)

if(RT_SVC_DECS_NUM==0)

//如果沒(méi)有服務(wù)要注冊(cè)

return;

(mems)et(rt_svc_descs_indices,

-1,sizeof(rt_svc_descs_indices));//初始化rt_svc_descs_indices

rt_svc_descs=(rt_svc_desc_t

*)RT_SVC_DESCS_START;//建立一個(gè)注冊(cè)表結(jié)構(gòu)體

for(index=0;indexinit)

{

//該服務(wù)是否需要初始化

rc=

service->init();

//進(jìn)行初始化

if(rc){

//初始化是否成功

ERROR("Errorinitializingruntimeservice%s",

service->name);

continue;

}

}

start_idx=

get_unique_oen(rt_svc_descs[index].start_oen,

service->call_type);

//八位的id號(hào)

assert(start_idxcall_type);

//八位的id號(hào)

assert(end_idx(RAM)

#else

ro.:{

__RO_START__=.;

*bl31_entrypoint.o(.text*)

*(SORT_BY_ALIGNMENT(.text*))

*(SORT_BY_ALIGNMENT(.rodata*))

RODATA_COMMON在include/common/bl_common.ld.h中

#define

RODATA_COMMON

RT_SVC_DESCS

FCONF_POPULATOR

PMF_SVC_DESCS

PARSER_LIB_DESCS

CPU_OPS

GOT

BASE_XLAT_TABLE_RO

EL3_LP_DESCS

#defineRT_SVC_DESCS

.=ALIGN(STRUCT_ALIGN);

__RT_SVC_DESCS_START__=

.;

KEEP(*(rt_svc_descs))

__RT_SVC_DESCS_END__=.;rt_svc_descs段存放的內(nèi)容是通過(guò)DECLARE_RT_SVC宏來(lái)定義的:

//其中__setion("rt_svc_descs")的意思就是注冊(cè)到rt_svc_descs段中

#define

DECLARE_RT_SVC(_name,_start,_end,_type,

_setup,_smch)

staticconstrt_svc_desc_t

__svc_desc_##_name

__section("rt_svc_descs")__used={

.start_oen=

(_start),

.end_oen=

(_end),

.call_type=

(_type),

.name=#_name,

.init=

(_setup),

.handle=

(_smch)

}例如在services/std_svc/std_svc_setup.c中

/*

RegisterStandardServiceCallsasruntimeservice*/

DECLARE_RT_SVC(

std_svc,

OEN_STD_START,

OEN_STD_END,

SMC_TYPE_FAST,

std_svc_setup,

std_svc_smc_handler

);

#defineOEN_STD_START

U(4)

/*StandardService

Calls*/

#defineOEN_STD_END

U(4)

#defineSMC_TYPE_FAST

UL(1)

#defineSMC_TYPE_YIELD

UL(0)staticconstrt_svc_desc_t__svc_desc_std_svc服務(wù)。其服務(wù)id為SMC_TYPE_FASTinit()會(huì)執(zhí)行std_svc_setup()函數(shù)

->psci_setup((constpsci_lib_args_t*)svc_arg)

(void)plat_setup_psci_ops((uintptr_t)lib_args->mailbox_ep,

plat_setup_psci_ops()的定義根據(jù)平臺(tái),我們使用的是qemu,對(duì)應(yīng)plat/qemu/qemu_sbsa/sbsa_pm.c文件中:

*psci_ops=

static

constplat_psci_ops_tplat_qemu_psci_pm_ops={

.cpu_standby=

qemu_cpu_standby,

.pwr_domain_on=

qemu_pwr_domain_on,

.pwr_domain_off=

qemu_pwr_domain_off,

.pwr_domain_pwr_down_wfi=

qemu_pwr_domain_pwr_down_wfi,

.pwr_domain_suspend=qemu_pwr_domain_suspend,

.pwr_domain_on_finish=

qemu_pwr_domain_on_finish,

.pwr_domain_suspend_finish=

qemu_pwr_domain_suspend_finish,

.system_off=qemu_system_off,

.system_reset=

qemu_system_reset,

.validate_power_state=

qemu_validate_power_state

};

4.4SMC異常處理入口分析

SMC命令執(zhí)行后,CPU會(huì)根據(jù)異常向量表找到sync_exception_aarch64的入口

會(huì)執(zhí)行handle_sync_exception,在bl31/aarch64/runtime_exceptions.S中

/*

*Thismacrohandles

Synchronousexceptions.

*OnlySMCexceptionsare

supported.

*

*/

.macro

handle_sync_exception

#ifENABLE_RUNTIME_INSTRUMENTATION

/*

*Readthetimestampvalueand

storeitinper-cpudata.Thevalue

*willbeextractedfrom

per-cpudatabytheClevelSMChandlerand

*savedtothePMFtimestamp

region.

*///存放時(shí)間戳

mrs

x30,cntpct_el0

str

x29,[sp,#CTX_GPREGS_OFFSET+

CTX_GPREG_X29]

mrs

x29,tpidr_el3

str

x30,[x29,#CPU_DATA_PMF_TS0_OFFSET]

ldr

x29,[sp,#CTX_GPREGS_OFFSET+

CTX_GPREG_X29]

#endif

mrs

x30,esr_el3

//將esr_el3存入x30

//#defineESR_EC_SHIFTU(26)

#defineESR_EC_LENGTHU(6)

//相當(dāng)于保留x30的bit[31-26]并將這幾位提到bit[6-0]

ubfx

x30,x30,#ESR_EC_SHIFT,#ESR_EC_LENGTH

/*HandleSMCexceptions

separatelyfromothersynchronousexceptions*/

cmp

x30,#EC_AARCH32_SMC

b.eq

smc_handler32

cmp

x30,#EC_AARCH64_SMC

b.eq

sync_handler64

cmp

x30,#EC_AARCH64_SYS

b.eq

sync_handler64

/*Synchronousexceptionsother

thantheaboveareassumedtobeEA*/

ldr

x30,[sp,#CTX_GPREGS_OFFSET+

CTX_GPREG_LR]

b

enter_lower_el_sync_ea

.endm三種跳轉(zhuǎn)選項(xiàng)其中smc_handler32/64能夠正確觸發(fā)異常,report_unhand(led)_exception則是錯(cuò)誤的流程

#define

EC_AARCH32_SMC

U(0x13)

#defineEC_AARCH64_SVC

U(0x15)

#defineEC_AARCH64_HVC

U(0x16)

#defineEC_AARCH64_SMC

U(0x17)x30里面存儲(chǔ)的是esr_el3的26-32位,里面是什么判斷了smc64

當(dāng)前平臺(tái)架構(gòu)是aarch64的,看一下sync_handler64這個(gè)處理,在bl31/aarch64/runtime_exceptions.S中

/*Loaddescriptorindexfromarray

ofindices*/

//在runtime_svc_init()中會(huì)將所有的sectionrt_svc_descs段放入rt_svc_descs_indices數(shù)組,

//這里獲取該數(shù)組地址

adrp

x14,rt_svc_descs_indices

add

x14,x14,rt_svc_descs_indices

ldrb

w15,[x14,x16]//找到rt_svc在rt_svc_descs_indices數(shù)組中的index

/*

*Getthedescriptorusingthe

index

*x11=(base+off),w15=

index這個(gè)index就是rt_svc_descs結(jié)構(gòu)體數(shù)組下標(biāo)

*

*handler=(base+off)+

(index

?bit31決定是fastcall,還是stdcall(yield對(duì)應(yīng)的就是stdcall)

?bit30表示是以32位傳參,還是以64位傳參,注意我們看了optee在linux的driver,都是以32位方式

?bit29:24決定服務(wù)的類(lèi)型

?bit23:16reserved

?bit15:0每種call類(lèi)型下,表示range

這個(gè)地方值為4,

/*

RegisterStandardServiceCallsasruntimeservice*/

DECLARE_RT_SVC(

std_svc,

OEN_STD_START,

OEN_STD_END,

SMC_TYPE_FAST,

std_svc_setup,

std_svc_smc_handler

);

#defineOEN_STD_START

U(4)

/*StandardServiceCalls*/

#defineOEN_STD_END

U(4)

系統(tǒng)啟動(dòng)的時(shí)候會(huì)把index信息存入到rt_svc_descs_indices里面,根據(jù)4取出來(lái)就可以了。

start_idx

=(uint8_t)get_unique_oen(service->start_oen,service->call_type);

end_idx=

(uint8_t)get_unique_oen(service->end_oen,service->call_type);

assert(start_idxsystem_off!=NULL);

/*NotifytheSecurePayload

Dispatcher*/

if((psci_spd_pm!=NULL)

}

console_flush();

/*Calltheplatformspecific

hook*/

psci_plat_pm_ops->system_off();

/*Thisfunctiondoesnot

return.Weshouldnevergethere*/

}psci_print_power_domain_map()的打印再和設(shè)備重啟時(shí)的日志進(jìn)行對(duì)比,發(fā)現(xiàn)是一致的。

4.5

硬件平臺(tái)相關(guān)處理

在qemu平臺(tái)上的實(shí)現(xiàn)如下:

psci_plat_pm_ops系統(tǒng)初始化的時(shí)候會(huì)賦值

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論