看完了ATF源代码,现在正在将代码移植到开发板上,配置了SCR_EL3=0x830(安全,AARCH32), SPSR_EL3=0x1d3(svc_mode,AARCH32,ARM指令集),ELR_EL3=0x40200000(BL32入口点地址),成功从BL31进入BL32初始化完成,返回BL31配置SCR_EL3=0x35(非安全),SPSR_EL3=0x1d3(svc_mode,AARCH32,ARM指令集),ELR_EL3=0x42000000(BL33入口点地址)却无法进入BL33,请问为什么?是虚拟化层EL2影响的吗?ps:源代码是默认执行AARCH64模式的BL33,但我的UBOOT是32位的,我修改了上诉寄存器期望进入32位的UBOOT执行,但失败了
从EL3通过eret返回到non secure EL1,这个是ARMv8架构支持的,应该不存在受EL2的影响。
能否更详细描述你的问题吗:
1) “无法进入BL33”, 是在调用 el3_exit(bl31_entrypoint.S) 里面的最后一条指令eret ,没有切换到BL33的entry?
有串口输出log吗? 在Makefile里面吧LOG_LEVEL改成50会给出更多log。
能用JTAG debugger调试更好了,比如DS-5,这样可以看出哪条指令出的问题。
2)请问你是在我们的开发板Juno上做的实验吗? 要是其他SOC厂商的方案,可能不是完全遵循ATF的实现来用。
3)关于memory使用,在你的配置下: Secure OS entry: ELR_EL3=0x40200000
uboot entry: ELR_EL3=0x42000000
uboot运行在非安全模式下,请问你的memory是非安全的memory吗? 要是在芯片里面有TZC400,需要配置memory region。
是在el3_exit里面的最后一条指令eret,没有切换到BL33的entry,没有log输出,LOG_LEVEL已近改为50了,还是没有,目测是根本没有跳转
不是juno板子,是三星的6818
我的是tzc380,UBOOT的memory配置成安全非安全均可以读写,配置的安全内存和UBOOT所使用到的内存没有重合,还是不行,既然不受EL2影响,为什么在源代码中还要配置EL2的寄存器啊,源代码如下:
void cm_prepare_el3_exit(uint32_t security_state)
{
uint32_t sctlr_elx, scr_el3;
uint32_t cptr_el2;
cpu_context_t *ctx = cm_get_context(security_state);
assert(ctx);
if (security_state == NON_SECURE) {
scr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_SCR_EL3);
if (scr_el3 & SCR_HCE_BIT) {
// Use SCTLR_EL1.EE value to initialise sctlr_el2
sctlr_elx = read_ctx_reg(get_sysregs_ctx(ctx),
CTX_SCTLR_EL1);
sctlr_elx &= ~SCTLR_EE_BIT;
sctlr_elx |= SCTLR_EL2_RES1;
write_sctlr_el2(sctlr_elx);
} else if (read_id_aa64pfr0_el1() &
(ID_AA64PFR0_ELX_MASK << ID_AA64PFR0_EL2_SHIFT)) {
// EL2 present but unused, need to disable safely
//HCR_EL2 = 0, except RW bit set to match SCR_EL3
write_hcr_el2((scr_el3 & SCR_RW_BIT) ? HCR_RW_BIT : 0);
//SCTLR_EL2 : can be ignored when bypassing
//CPTR_EL2 : disable all traps TCPAC, TTA, TFP
cptr_el2 = read_cptr_el2();
cptr_el2 &= ~(TCPAC_BIT | TTA_BIT | TFP_BIT);
write_cptr_el2(cptr_el2);
// Enable EL1 access to timer
write_cnthctl_el2(EL1PCEN_BIT | EL1PCTEN_BIT);
//Reset CNTVOFF_EL2
write_cntvoff_el2(0);
// Set VPIDR, VMPIDR to match MIDR, MPIDR
write_vpidr_el2(read_midr_el1());
write_vmpidr_el2(read_mpidr_el1());
// Reset VTTBR_EL2.
// Needed because cache maintenance operations depend on
// the VMID even when non-secure EL1&0 stage 2 address
// translation are disabled.
write_vttbr_el2(0);
}
el1_sysregs_context_restore(get_sysregs_ctx(ctx));
cm_set_next_context(ctx);
> 是在el3_exit里面的最后一条指令eret,没有切换到BL33的entry,没有log输出,LOG_LEVEL已近改为50了,还是没有,目测是根本没有跳转
你这里方便用debugger看看运行eret指令后系统跑到哪里去了?
我这里修改了了SCR_EL3 (=0x35) 在FVP上 跑uboot Aarch32,eret后切换是成功的, 下面我是修改的代码:
+++ b/plat/arm/common/aarch64/arm_common.c
@@ -119,22 +119,18 @@ uint32_t arm_get_spsr_for_bl32_entry(void)
******************************************************************************/
uint32_t arm_get_spsr_for_bl33_entry(void)
- unsigned long el_status;
- unsigned int mode;
uint32_t spsr;
- /* Figure out what mode we enter the non-secure world in */
- el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
- el_status &= ID_AA64PFR0_ELX_MASK;
-
- mode = (el_status) ? MODE_EL2 : MODE_EL1;
/*
* TODO: Consider the possibility of specifying the SPSR in
* the FIP ToC and allowing the platform to have a say as
* well.
*/
- spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+ SPSR_E_LITTLE,
+ DAIF_FIQ_BIT |
+ DAIF_IRQ_BIT |
+ DAIF_ABT_BIT);
return spsr;
设置sctlr_el2正常,cpu 开机后,将系统管理寄存器设置好初值。
正常启动下面BL33/uboot其实运行在EL2里面,到kernel里面也是, stext(arch/arm64/kernel/head.S),然后再切换到NS EL1。
三星方案中应该只用了EL3 monitor, 也就是BL31吧?
你有对比测试吗? 比如什么都不修改,直接进入UBOOT 缺省AArch64, 这样OK吗?
“你这里方便用debugger看看运行eret指令后系统跑到哪里去了?”
没有JTAG口看不了
“我这里修改了了SCR_EL3 (=0x35) 在FVP上 跑uboot Aarch32,eret后切换是成功的, 下面我是修改的代码:”
我也是这么改的,不行哦,要哭了
“正常启动下面BL33/uboot其实运行在EL2里面,到kernel里面也是, stext(arch/arm64/kernel/head.S),然后再切换到NS EL1。”
UBOOT再64位模式下运行在EL2,linux内核再切换到NS EL1
UBOOT再32位模式下以svc权限运行,可以以hyp模式运行吗?
"三星方案中应该只用了EL3 monitor, 也就是BL31吧?"
读取read_id_aa64pfr0_el1()==0x01002222,应该是EL0 EL1 EL2 EL3都支持的
“你有对比测试吗? 比如什么都不修改,直接进入UBOOT 缺省AArch64, 这样OK吗?”
UBOOT的AARCH64 AARCH32都试过了,不行
>> “正常启动下面BL33/uboot其实运行在EL2里面,到kernel里面也是, stext(arch/arm64/kernel/head.S),然后再切换到NS EL1。”
> UBOOT再64位模式下运行在EL2,linux内核再切换到NS EL1
> UBOOT再32位模式下以svc权限运行,可以以hyp模式运行吗?
这样做有什么意义? 假如你不跑hypervisor的话
>> "三星方案中应该只用了EL3 monitor, 也就是BL31吧?"
> 读取read_id_aa64pfr0_el1()==0x01002222,应该是EL0 EL1 EL2 EL3都支持的
我的意思是缺省的ATF里面的Images, 该SOC厂商只采用BL31,其它的,比如 BL1和BL2没有采用ATF的实现。
>“你有对比测试吗? 比如什么都不修改,直接进入UBOOT 缺省AArch64, 这样OK吗?”
> UBOOT的AARCH64 AARCH32都试过了,不行
这说明不是这几个registers配置的问题。
你采用三星原来板子带的ATF firmware可以跑起来吗? 他们有没有开放他们芯片对应的ATF的代码? 也许他们的硬件配置和缺省的不一样。 我没有在ATF代码里面看到三星的实现。
“你采用三星原来板子带的ATF firmware可以跑起来吗? 他们有没有开放他们芯片对应的ATF的代码? 也许他们的硬件配置和缺省的不一样。 我没有在ATF代码里面看到三星的实现。”
他们没有开放他们芯片对应的ATF代码,应该说根本就没有,正是由于ATF代码中没有三星的实现,所以我正在做啊,BL1 BL2 BL31 BL32都起来了,就差最后一步进入BL33了,不容易啊
谢谢你的回答,要是我这个问题解决了会通知你的
你的目的是为了做什么? 一定要三星这个chip上跑ATF吗?
Linaro推出96boards,其中华为海思的HiKey Board,有对应的代码 HiKeyGettingStarted · 96boards/documentation Wiki · GitHub
当然ATF对ARM Juno板是原生支持。
有些好奇,ATF 在github上的代码不包括Samsung芯片的支持,整个移植都是你自己做的吗? 还是三星有提供代码。
你这个问题感觉和memory的配置有关, 但是你的调试手段有限。 尝试把SCR_EL3.EA bit使能,这样让exception都路由到EL3的exception handler,然后你在EL3 handler里面加打印,看看能否有一些错误信息。
"整个移植都是你自己做的吗? "
自己做的,他们只提供芯片手册
“ 尝试把SCR_EL3.EA bit使能,这样让exception都路由到EL3的exception handler,然后你在EL3 handler里面加打印,看看能否有一些错误信息。”
这是个好方法!
“你这个问题感觉和memory的配置有关”
问题找到了,不是内存配置的问题,是安全外设的问题,没有配置TZPC寄存器,串口默认为安全的,在安全世界正常打印出数据,进入到BL33非安全世界就打印不了了,实际上是进入了BL33的,将串口配置成非安全的就行了
非常感谢你的回答