Skip to content

Commit cca8110

Browse files
committed
Add the iretq function to the InterruptStackFrameValue struct.
1 parent 5dbcc9f commit cca8110

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

src/structures/idt.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,39 @@ pub struct InterruptStackFrameValue {
942942
pub stack_segment: u64,
943943
}
944944

945+
impl InterruptStackFrameValue {
946+
/// Call the `iretq` (interrupt return) instruction.
947+
///
948+
/// It is not required to be in a interrupt handler to be able to call this instruction.
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+
pub unsafe fn iretq(&self) -> ! {
959+
unsafe {
960+
core::arch::asm!(
961+
"push {data_segment}",
962+
"push {new_stack_pointer}",
963+
"push {rflags}",
964+
"push {code_segment}",
965+
"push {new_instruction_pointer}",
966+
"iretq",
967+
rflags = in(reg) self.cpu_flags,
968+
new_instruction_pointer = in(reg) self.instruction_pointer.as_u64(),
969+
new_stack_pointer = in(reg) self.stack_pointer.as_u64(),
970+
code_segment = in(reg) self.code_segment,
971+
data_segment = in(reg) self.stack_segment,
972+
options(noreturn)
973+
)
974+
}
975+
}
976+
}
977+
945978
impl fmt::Debug for InterruptStackFrameValue {
946979
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
947980
struct Hex(u64);

0 commit comments

Comments
 (0)