




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第第页电源管理入门-关机重启基础知识详解当我们接触(电源管理)的时候,最简单的流程就是
关机重启
,但是仔细分析其涉及的所有源代码就会发现,关机重启虽然简单,但是“
麻雀虽小,五脏俱全
”,涉及到的软件模块非常的多,涉及的流程:(Linux)应用(busybox)-》Linux内核-》BL31-》SCP-》(PMIC)/CRU等(硬件)。所以是一个入门学习,特别是还没接触过Linux内核代码的好机会,下面进入代码的海洋遨游,
超级干货
!
1.关机重启软件流程框图
在Linux系统上的处理分为**用户态**空间、**内核**空间、**ATF**、**SCP**四个阶段(ATF是(ARM)独有的,SCP在复杂SoC上才有应用)来处理:
BL31中smc异常触发流程图
执行SMC指令后会触发异常,进入ATF的BL31中继续执行:
在Linux侧调用smc异常之后,会根据中断向量表触发cpu的同步异常sync_exception_aarch64/32
然后跳转执行到handle_sync_exception->smc_handler64/32中
根据_RT_SVC_DESCS_START_+RT_SVC_DESC_HANDLE的位置,跳转执行rt_svc_desc_t结构体保存的服务std_svc_smc_handler
执行psci相关处理,找到psci_system_off和psci_system_rese处理函数。ATF直接处理如果是关机就执行halt指令,重启则通过设置gpio,或者转送给SCP处理。
最后跳转到el3_exit返回Linux侧。
SMC异常触发执行流程:
(32*4)
//这个.应该是当前位置-段的开头地址如果大于32条指令
.error"Vectorexceeds
32instructions"
//向量超过32条指令
.endif4.3
runtime服务程序初始化
bl31_entrypoint入口向下执行首先是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()函数:
void
bl31_main(void)
{
NOTICE("BL31:%s",
version_string);
NOTICE("BL31:%s",
build_message);
bl31_platform_setup();
//通用和安全(时钟)初始化,其他(芯片)相关功能初始化
bl31_lib_init();
//空函数
INFO("BL31:Initializing
runtimeservices");
runtime_svc_init();
//重点下面展开分析
if(bl32_init){
INFO("BL31:
InitializingBL32");
(*bl32_init)();
}
bl31_prepare_next_image_entry();
//加载下一阶段的入口地址
console_flush();
//控制台刷新
bl31_plat_runtime_setup();
//空函数
}runtime_svc_init()函数
//注册smc指令相关的服务
voidruntime_svc_init(void)
{
intrc=0;
unsignedintindex,start_idx,
end_idx;
/*Assertthenumberof
descriptorsdetectedarelessthan(maxim)umindices*/
//这句话表明
RT_SVC_DECS_NUM时当前加载的服务数量
assert((RT_SVC_DESCS_END>=
RT_SVC_DESCS_START)
if(RT_SVC_DECS_NUM==0)
//如果没有服务要注册
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;//建立一个注册表结构体
for(index=0;indexinit)
{
//该服务是否需要初始化
rc=
service->init();
//进行初始化
if(rc){
//初始化是否成功
ERROR("Errorinitializingruntimeservice%s",
service->name);
continue;
}
}
start_idx=
get_unique_oen(rt_svc_descs[index].start_oen,
service->call_type);
//八位的id号
assert(start_idxcall_type);
//八位的id号
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段存放的内容是通过DECLARE_RT_SVC宏来定义的:
//其中__setion("rt_svc_descs")的意思就是注册到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服务。其服务id为SMC_TYPE_FASTinit()会执行std_svc_setup()函数
->psci_setup((constpsci_lib_args_t*)svc_arg)
(void)plat_setup_psci_ops((uintptr_t)lib_args->mailbox_ep,
plat_setup_psci_ops()的定义根据平台,我们使用的是qemu,对应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命令执行后,CPU会根据异常向量表找到sync_exception_aarch64的入口
会执行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.
*///存放时间戳
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)
//相当于保留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三种跳转选项其中smc_handler32/64能够正确触发异常,report_unhand(led)_exception则是错误的流程
#define
EC_AARCH32_SMC
U(0x13)
#defineEC_AARCH64_SVC
U(0x15)
#defineEC_AARCH64_HVC
U(0x16)
#defineEC_AARCH64_SMC
U(0x17)x30里面存储的是esr_el3的26-32位,里面是什么判断了smc64
当前平台架构是aarch64的,看一下sync_handler64这个处理,在bl31/aarch64/runtime_exceptions.S中
/*Loaddescriptorindexfromarray
ofindices*/
//在runtime_svc_init()中会将所有的sectionrt_svc_descs段放入rt_svc_descs_indices数组,
//这里获取该数组地址
adrp
x14,rt_svc_descs_indices
add
x14,x14,rt_svc_descs_indices
ldrb
w15,[x14,x16]//找到rt_svc在rt_svc_descs_indices数组中的index
/*
*Getthedescriptorusingthe
index
*x11=(base+off),w15=
index这个index就是rt_svc_descs结构体数组下标
*
*handler=(base+off)+
(index
•bit31决定是fastcall,还是stdcall(yield对应的就是stdcall)
•bit30表示是以32位传参,还是以64位传参,注意我们看了optee在linux的driver,都是以32位方式
•bit29:24决定服务的类型
•bit23:16reserved
•bit15:0每种call类型下,表示range
这个地方值为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)
系统启动的时候会把index信息存入到rt_svc_descs_indices里面,根据4取出来就可以了。
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()的打印再和设备重启时的日志进行对比,发现是一致的。
4.5
硬件平台相关处理
在qemu平台上的实现如下:
psci_plat_pm_ops系统初始化的时候会赋值
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 苏州市重点中学2024-2025学年数学高二下期末监测试题含解析
- 天津开发区第一中学2025年高二下物理期末考试模拟试题含解析
- 浙江省杭州二中2025届物理高二第二学期期末质量跟踪监视试题含解析
- 电力设备采购人员保密及竞业禁止合同范本
- 储油罐租赁与油气市场分析服务合同
- 酒店业财务出纳责任保证合同
- 2024年厦门银行重庆分招聘笔试真题
- 2024年陇南市青少年军校招聘笔试真题
- 加油站操作员中级工练习试题
- 掘进机司机练习试题附答案
- 深圳市城市规划案例分析2
- 0-3岁婴幼儿生活照护智慧树知到期末考试答案章节答案2024年运城幼儿师范高等专科学校
- 基于单元主题的小学英语跨学科学习活动的实践与研究
- 2024年广东省高考化学试卷(真题+答案)
- 网络信息安全防护管理质量评价标准
- 中医食疗学智慧树知到期末考试答案2024年
- 康保县中矿矿业有限公司孔督沟萤石矿矿山地质环境保护与土地复垦方案
- 眩晕护理常规课件
- 2024中考英语1500词汇默写汇总表练习(含答案)
- 2023年全国统考《不动产登记代理实务》考前冲刺备考200题(含详解)
- 农夫山泉财务能力分析报告
评论
0/150
提交评论