@@ -942,6 +942,40 @@ pub struct InterruptStackFrameValue {
942
942
pub stack_segment : u64 ,
943
943
}
944
944
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
+
945
979
impl fmt:: Debug for InterruptStackFrameValue {
946
980
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
947
981
struct Hex ( u64 ) ;
0 commit comments