use core::arch::asm; use x86_64::registers::rflags::RFlags; pub struct EnterUserModeInput { pub rip: u64, pub rsp: u64, pub rflags: RFlags } /// # Safety /// Does `sysretq` /// Make sure that you are not letting the user space program do things you /// don't want it to do. You must enable system call extensions first. pub unsafe fn enter_user_mode(EnterUserModeInput { rip, rsp, rflags }: EnterUserModeInput) -> ! { let rflags = rflags.bits(); unsafe { // Note that we do `sysretq` and not `sysret` because if we just do // `sysret`, that could be compiled into a `sysretl`, which is for // 32-bit compatibility mode and can mess things up. asm!("\ mov rsp, {} sysretq", in(reg) rsp, in("rcx") rip, in("r11") rflags, // The user space program can only "return" with a `syscall`, whic // will jump to the syscall handler options(noreturn) ); } }