I am trying to write simple efi application that change the exception level from el2 64bit to el1 64 bit but with no success.
void entry_el1(void){
Print (L"running in el1.\n\r");
}
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
__asm__ volatile (
"mov x0, #(1 << 31)\n\t"
"msr hcr_el2, x0\n\t"
"mov x0, #0x0800\n\t"
"movk x0, #0x30d0, lsl #16\n\t"
"msr sctlr_el1, x0\n\t"
"mov x0, #0x33ff\n\t"
"msr cptr_el2, x0\n\t"
"msr hstr_el2, xzr\n\t"
"mov x0, #0x3c5\n\t"
"msr spsr_el2, x0\n\t"
"mov x0, %0\n\t"
"msr elr_el2, x0\n\t"
"eret" : : "r" (entry_el1) :
);
return EFI_SUCCESS;
}
After running this nothing happens! Is this the correct procedure for changing exception level?
答案 0 :(得分:1)
假设它并不是简单地在内联asm上缺少一个clobber列表导致你的ELR_EL2地址被删除(在这种情况下直接跳到&#34;触发异常&#34;下面),我认为你很好地堕入EL1;当你到达那里时,麻烦就开始了......
作为非叶C函数,entry_el1
要做的第一件事就是将返回地址推送到堆栈(或者如果编译器足够聪明以将其优化为尾调用没有堆栈框架,那么Print
的序幕是那样做的人,但同样的事情)。除了我们处理器模式(EL1h),这意味着除非任何人都在使用SPSel,否则我们的堆栈指针是SP_EL1,此时可能包含未初始化的无意义。因此,堆栈访问几乎肯定会触发异常,但是我们在EL1处,因此异常被用于VBAR_EL1指向的向量,此时可能包含未初始化的无意义。那么你好,通过递归异常锁定死亡。
如果你要与Linux入门代码进行比较,那么重要的是要注意当从(EL2)下降时,它仍会进入更多的裸机汇编代码在它接近C代码之前将EL1从头开始设置 - 实际上,设置一个堆栈指针是它最后的最后之一。