1

我正在尝试编写简单的 efi 应用程序,将异常级别从 el2 64 位更改为 el1 64 位,但没有成功。

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;
}

运行后没有任何反应!这是更改异常级别的正确程序吗?

4

1 回答 1

1

假设这不仅仅是内联汇编中缺少一个clobber列表导致您的ELR_EL2地址被丢弃(在这种情况下直接跳到下面的“触发异常”),我认为您下降到EL1就好了;当你到达那里时,麻烦就开始了……

作为非叶 C 函数,首先要做的entry_el1是将返回地址压入堆栈(或者如果编译器足够聪明地将其优化为没有堆栈帧的尾调用,那么序言Print就是那个家伙这样做,但同样的事情)。除了我们处于处理程序模式(EL1h)之外,这意味着除非有人一直在弄乱 SPSel,否则我们的堆栈指针是 SP_EL1,此时它可能包含未初始化的废话。因此,堆栈访问几乎肯定会触发异常,但我们处于 EL1,因此异常被带到 VBAR_EL1 指向的向量,此时可能包含未初始化的废话。你好,递归异常导致锁定死亡。

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

于 2015-10-31T13:35:24.503 回答