@@ -942,6 +942,40 @@ pub struct InterruptStackFrameValue {
942942 pub stack_segment : u64 ,
943943}
944944
945+ impl InterruptStackFrameValue {
946+ /// Call the `iretq` (interrupt return) instruction.
947+ ///
948+ /// This function doesn't have to be called in an interrupt handler.
949+ /// By manually construction a new [`InterruptStackFrameValue`] it's possible to transition
950+ /// from a higher privilege level to a lower one.
951+ ///
952+ /// ## Safety
953+ ///
954+ /// Calling `iretq` is unsafe because setting the instruction pointer, stack pointer, RFlags,
955+ /// CS and SS register can all cause undefined behaviour when done incorrectly.
956+ ///
957+ #[ inline( always) ]
958+ #[ cfg( feature = "instructions" ) ]
959+ pub unsafe fn iretq ( & self ) -> ! {
960+ unsafe {
961+ core:: arch:: asm!(
962+ "push {stack_segment}" ,
963+ "push {new_stack_pointer}" ,
964+ "push {rflags}" ,
965+ "push {code_segment}" ,
966+ "push {new_instruction_pointer}" ,
967+ "iretq" ,
968+ rflags = in( reg) self . cpu_flags,
969+ new_instruction_pointer = in( reg) self . instruction_pointer. as_u64( ) ,
970+ new_stack_pointer = in( reg) self . stack_pointer. as_u64( ) ,
971+ code_segment = in( reg) self . code_segment,
972+ stack_segment = in( reg) self . stack_segment,
973+ options( noreturn)
974+ )
975+ }
976+ }
977+ }
978+
945979impl fmt:: Debug for InterruptStackFrameValue {
946980 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
947981 struct Hex ( u64 ) ;
0 commit comments