armv8 changing exception level from el2 to el1

时间:2015-10-30 21:42:48

标签: exception arm uefi

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?

1 个答案:

答案 0 :(得分:1)

假设它并不是简单地在内联asm上缺少一个clobber列表导致你的ELR_EL2地址被删除(在这种情况下直接跳到&#34;触发异常&#34;下面),我认为你很好地堕入EL1;当你到达那里时,麻烦就开始了......

作为非叶C函数,entry_el1要做的第一件事就是将返回地址推送到堆栈(或者如果编译器足够聪明以将其优化为尾调用没有堆栈框架,那么Print的序幕是那样做的人,但同样的事情)。除了我们处理器模式(EL1h),这意味着除非任何人都在使用SPSel,否则我们的堆栈指针是SP_EL1,此时可能包含未初始化的无意义。因此,堆栈访问几乎肯定会触发异常,但是我们在EL1处,因此异常被用于VBAR_EL1指向的向量,此时可能包含未初始化的无意义。那么你好,通过递归异常锁定死亡。

如果你要与Linux入门代码进行比较,那么重要的是要注意当从(EL2)下降时,它仍会进入更多的裸机汇编代码在它接近C代码之前将EL1从头开始设置 - 实际上,设置一个堆栈指针是它最后的最后之一。