我正致力于在一个不支持本机环3的单一内核上启用Intel。因此,为了调用用户模式的SGX指令,我需要实现一个环形开关例程。我遵循JamesM的教程( 10.-用户模式(jamesmolloy.co.uk),这是一个32位的解决方案)起草了一个长模式版本:
void switch_to_ring3()
{
asm volatile(" \
mov $0x23, %rax; \
mov %rax, %ds; \
mov %rax, %es; \
mov %rsp, %rax; \
push $0x23; \
push %rax; \
pushf; \
push $0x1B; \
push $1f; \
iretq; \
1: \
");
return;
}我确信我已经正确地设置了GDT条目,而0x23/0x1B正是用户模式代码/数据描述符的索引,其中代码描述符值是0xaffb000000ffff,数据描述符值是0xaff3000000ffff。
奇怪的是,iretq可以成功地执行,rip寄存器可以转到iretq的下一个指令,如果我禁用优化,它是一个nop,如果启用优化,则是一个ret。但是,在执行下一条指令时,它将在没有任何输出的情况下死亡(我的unikernel有一个异常处理程序,即使对于未处理的异常,它也会输出一些东西)。我试着用GDB来调试,GDB说这个程序收到了SIGQUIT。
我检查了寄存器,但是没有发现任何错误,cs是0x1b,ss,ds和es是0x23,rip正确地指向iretq的下一个指令。
我真的很困惑为什么它会收到SIGQUIT。如果发生异常,它应该输出转储消息,或者至少qemu日志将跟踪一些“check_exception”消息,但是日志是空的。一切看起来都很好,正确的段寄存器,正确的rsp/rbp/rip,内核代码段可以通过设置描述符的一致位来访问,并且所有描述符中的高/低基址都指向0x0。
被困在这个问题上一整天,但找不到任何解决办法。我希望这里有人能救我的命T_T
发布于 2022-06-09 07:10:13
最后,我通过为所有内核代码/数据页设置U/S位来修复它。谢谢你的评论@prl @PeterCordes!
https://stackoverflow.com/questions/72546941
复制相似问题