Skip to content

Commit 41a10bb

Browse files
authored
Merge pull request #431 from NathanKolpa/master
Add the `iretq` function to the `InterruptStackFrameValue` struct.
2 parents 5dbcc9f + 298215f commit 41a10bb

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

src/structures/idt.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
945979
impl fmt::Debug for InterruptStackFrameValue {
946980
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
947981
struct Hex(u64);

0 commit comments

Comments
 (0)