Code: Select all
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;
What's strange is that the iretq can be executed successfully, and the rip register could go to the next instruction of the iretq, which is a nop if I disabled the optimization and a ret if I enabled the optimization. However, when executing the next instruction, it will die without any output (my unikernel has an exception handler, even if for unhandled exceptions, it will output something). I try to use GDB to debug and GDB said that the program received SIGQUIT.
I checked the registers but find nothing wrong, cs is 0x1b, ss, ds and es are 0x23, and rip points correctly to the next instruction of iretq.
I am really confused about why it receives SIGQUIT. If some exception happened, it should output the dump message, or at least qemu log will track some 'check_exception' message, but the log is empty. Everything seems okay, correct segment registers, correct rsp/rbp/rip, the kernel code segment is user-accessible by setting the conformed bit of its descriptor, and the high/low base address in all descriptors are pointed to 0x0.
Being trapped in this problem for a whole day but cannot find any solution. I hope someone here could save my life T_T