x86/bits32/
eflags.rs

1//! Processor state stored in the EFLAGS register.
2
3use bitflags::*;
4
5use crate::Ring;
6use core::arch::asm;
7
8bitflags! {
9    /// The EFLAGS register.
10    pub struct EFlags: u32 {
11        /// ID Flag (ID)
12        const FLAGS_ID = 1 << 21;
13        /// Virtual Interrupt Pending (VIP)
14        const FLAGS_VIP = 1 << 20;
15        /// Virtual Interrupt Flag (VIF)
16        const FLAGS_VIF = 1 << 19;
17        /// Alignment Check (AC)
18        const FLAGS_AC = 1 << 18;
19        /// Virtual-8086 Mode (VM)
20        const FLAGS_VM = 1 << 17;
21        /// Resume Flag (RF)
22        const FLAGS_RF = 1 << 16;
23        /// Nested Task (NT)
24        const FLAGS_NT = 1 << 14;
25        /// I/O Privilege Level (IOPL) 0
26        const FLAGS_IOPL0 = 0b00 << 12;
27        /// I/O Privilege Level (IOPL) 1
28        const FLAGS_IOPL1 = 0b01 << 12;
29        /// I/O Privilege Level (IOPL) 2
30        const FLAGS_IOPL2 = 0b10 << 12;
31        /// I/O Privilege Level (IOPL) 3
32        const FLAGS_IOPL3 = 0b11 << 12;
33        /// Overflow Flag (OF)
34        const FLAGS_OF = 1 << 11;
35        /// Direction Flag (DF)
36        const FLAGS_DF = 1 << 10;
37        /// Interrupt Enable Flag (IF)
38        const FLAGS_IF = 1 << 9;
39        /// Trap Flag (TF)
40        const FLAGS_TF = 1 << 8;
41        /// Sign Flag (SF)
42        const FLAGS_SF = 1 << 7;
43        /// Zero Flag (ZF)
44        const FLAGS_ZF = 1 << 6;
45        /// Auxiliary Carry Flag (AF)
46        const FLAGS_AF = 1 << 4;
47        /// Parity Flag (PF)
48        const FLAGS_PF = 1 << 2;
49        /// Bit 1 is always 1.
50        const FLAGS_A1 = 1 << 1;
51        /// Carry Flag (CF)
52        const FLAGS_CF = 1 << 0;
53    }
54}
55
56impl EFlags {
57    /// Creates a new Flags entry. Ensures bit 1 is set.
58    pub const fn new() -> EFlags {
59        EFlags::FLAGS_A1
60    }
61
62    /// Creates a new Flags with the given I/O privilege level.
63    pub const fn from_priv(iopl: Ring) -> EFlags {
64        EFlags {
65            bits: (iopl as u32) << 12,
66        }
67    }
68}
69
70#[cfg(target_arch = "x86")]
71#[inline(always)]
72pub unsafe fn read() -> EFlags {
73    let r: u32;
74    asm!("pushfl; popl {0}", out(reg) r, options(att_syntax));
75    EFlags::from_bits_truncate(r)
76}
77
78#[cfg(target_arch = "x86")]
79#[inline(always)]
80pub unsafe fn set(val: EFlags) {
81    asm!("pushl {0}; popfl", in(reg) val.bits(), options(att_syntax));
82}
83
84/// Clears the AC flag bit in EFLAGS register.
85///
86/// This disables any alignment checking of user-mode data accesses.
87/// If the SMAP bit is set in the CR4 register, this disallows
88/// explicit supervisor-mode data accesses to user-mode pages.
89///
90/// # Safety
91///
92/// This instruction is only valid in Ring 0 and requires
93/// that the CPU supports the instruction (check CPUID).
94#[inline(always)]
95pub unsafe fn clac() {
96    asm!("clac");
97}
98
99/// Sets the AC flag bit in EFLAGS register.
100///
101/// This may enable alignment checking of user-mode data accesses.
102/// This allows explicit supervisor-mode data accesses to user-mode
103/// pages even if the SMAP bit is set in the CR4 register.
104///
105/// # Safety
106///
107/// This instruction is only valid in Ring 0 and requires
108/// that the CPU supports the instruction (check CPUID).
109#[inline(always)]
110pub unsafe fn stac() {
111    asm!("stac");
112}