armv8 将异常级别从 el2 更改为 el1
armv8 changing exception level from el2 to el1
我正在尝试编写简单的 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;
}
在运行之后什么也没有发生!这是更改异常级别的正确程序吗?
假设不仅仅是内联 asm 上缺少破坏列表导致你的 ELR_EL2 地址被破坏(在这种情况下直接跳到下面的 "triggers an exception"),我认为你是降到 EL1 就好了;当您到达那里时,麻烦就开始了...
作为非叶 C 函数,entry_el1
要做的第一件事是将 return 地址压入堆栈(或者如果编译器足够聪明将其优化为没有堆栈框架的尾调用,那么 Print
的序言就是这样做的人,但同样的事情)。除了我们处于处理程序模式 (EL1h) 之外,这意味着除非有人在乱用 SPSel,否则我们的堆栈指针是 SP_EL1,此时它可能包含未初始化的废话。因此,堆栈访问几乎肯定会触发异常,但我们处于 EL1,因此异常被带到 VBAR_EL1 指向的向量,此时可能包含未初始化的废话。你好,递归异常导致锁死。
如果您正在与 Linux 入口代码进行比较,那么请务必注意,当(如果)从 EL2 下降时,它仍然会进入更多设置 EL1 的裸机汇编代码在接近 C 代码之前从头开始 - 实际上,设置堆栈指针是它所做的最后事情之一。
我正在尝试编写简单的 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;
}
在运行之后什么也没有发生!这是更改异常级别的正确程序吗?
假设不仅仅是内联 asm 上缺少破坏列表导致你的 ELR_EL2 地址被破坏(在这种情况下直接跳到下面的 "triggers an exception"),我认为你是降到 EL1 就好了;当您到达那里时,麻烦就开始了...
作为非叶 C 函数,entry_el1
要做的第一件事是将 return 地址压入堆栈(或者如果编译器足够聪明将其优化为没有堆栈框架的尾调用,那么 Print
的序言就是这样做的人,但同样的事情)。除了我们处于处理程序模式 (EL1h) 之外,这意味着除非有人在乱用 SPSel,否则我们的堆栈指针是 SP_EL1,此时它可能包含未初始化的废话。因此,堆栈访问几乎肯定会触发异常,但我们处于 EL1,因此异常被带到 VBAR_EL1 指向的向量,此时可能包含未初始化的废话。你好,递归异常导致锁死。
如果您正在与 Linux 入口代码进行比较,那么请务必注意,当(如果)从 EL2 下降时,它仍然会进入更多设置 EL1 的裸机汇编代码在接近 C 代码之前从头开始 - 实际上,设置堆栈指针是它所做的最后事情之一。