/rust/registry/src/index.crates.io-1949cf8c6b5b557f/x86-0.47.0/src/bits32/eflags.rs
Line | Count | Source |
1 | | //! Processor state stored in the EFLAGS register. |
2 | | |
3 | | use bitflags::*; |
4 | | |
5 | | use crate::Ring; |
6 | | use core::arch::asm; |
7 | | |
8 | | bitflags! { |
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 | | |
56 | | impl EFlags { |
57 | | /// Creates a new Flags entry. Ensures bit 1 is set. |
58 | 0 | pub const fn new() -> EFlags { |
59 | 0 | EFlags::FLAGS_A1 |
60 | 0 | } |
61 | | |
62 | | /// Creates a new Flags with the given I/O privilege level. |
63 | 0 | pub const fn from_priv(iopl: Ring) -> EFlags { |
64 | 0 | EFlags { |
65 | 0 | bits: (iopl as u32) << 12, |
66 | 0 | } |
67 | 0 | } |
68 | | } |
69 | | |
70 | | #[cfg(target_arch = "x86")] |
71 | | #[inline(always)] |
72 | | pub 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)] |
80 | | pub 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)] |
95 | 0 | pub unsafe fn clac() { |
96 | 0 | asm!("clac"); |
97 | 0 | } |
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)] |
110 | 0 | pub unsafe fn stac() { |
111 | 0 | asm!("stac"); |
112 | 0 | } |