从0号环切换到3号环时非常奇怪的SIGQUIT



我正在一个没有原生环3支持的单内核上启用英特尔SGX。因此,为了调用用户模式SGX指令,我需要实现一个环形开关例程。我遵循了james的教程(10)。-用户模式(jamesmolloy.com .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

我最终通过为所有内核代码/数据页设置U/S位来修复它。谢谢你的评论@prl @PeterCordes !

相关内容

  • 没有找到相关文章

最新更新