1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
//! x86_64 specific
pub mod interrupt;
pub mod intrinsics;
pub mod msr;
pub mod pio;
pub mod segmentation;
pub mod table;
pub mod tss;
use core::arch::asm;
/// Privilege Levels.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum PrivilegeLevel {
Ring0 = 0,
Ring1 = 1,
Ring2 = 2,
Ring3 = 3,
}
bitflags::bitflags! {
/// rflags.
#[repr(transparent)]
pub struct Rflags: u64 {
/// Carry Flag
const CF = 1 << 0;
/// Must be 1.
const _1 = 1 << 1;
/// Parity Flag
const PF = 1 << 2;
/// Adjust Flag
const AF = 1 << 4;
/// Zero Flag
const ZF = 1 << 6;
/// Sign Flag
const SF = 1 << 7;
/// Trap Flag
const TF = 1 << 8;
/// Interrupt enable.
///
/// Controls the response of the processor to maskable hardware
/// interrupt requests (see also: Section 6.3.2, "Maskable
/// Hardware Interrupts"). The flag is set to respond to maskable
/// hardware interrupts; cleared to inhibit maskable hardware
/// interrupts. The IF flag does not affect the generation of exceptions
/// or nonmaskable interrupts (NMI interrupts). The CPL, IOPL, and the
/// state of the VME flag in control register CR4 determine
/// whether the IF flag can be modified by the CLI, STI, POPF, POPFD,
/// and IRET.
const IF = 1 << 9;
/// Direction Flag
const DF = 1 << 10;
/// Overflow Flag
const OF = 1 << 11;
/// I/O privilege level field - bit 0
///
/// Indicates the I/O privilege level (IOPL) of the currently
/// running program or task. The CPL of the currently running program or
/// task must be less than or equal to the IOPL to access the
/// I/O address space. The POPF and IRET instructions can modify this
/// field only when operating at a CPL of 0.
///
/// The IOPL is also one of the mechanisms that controls the
/// modification of the IF flag and the handling of interrupts
/// in virtual-8086 mode when virtual mode extensions are in effect
/// (when CR4.VME = 1).
///
/// See also: Chapter 18, "Input/Output," in
/// the Intel® 64 and IA-32 Architectures Software Developer’s Manual,
/// Volume 1.
const IOPL0 = 1 << 12;
/// I/O privilege level field - bit 1
///
/// Indicates the I/O privilege level (IOPL) of the currently
/// running program or task. The CPL of the currently running program or
/// task must be less than or equal to the IOPL to access the
/// I/O address space. The POPF and IRET instructions can modify this
/// field only when operating at a CPL of 0.
/// The IOPL is also one of the mechanisms that controls the
/// modification of the IF flag and the handling of interrupts
/// in virtual-8086 mode when virtual mode extensions are in effect
/// (when CR4.VME = 1).
///
/// See also: Chapter 18, "Input/Output," in the Intel® 64 and IA-32
/// Architectures Software Developer’s Manual, Volume 1.
const IOPL1 = 1 << 13;
/// Nested task
///
/// Controls the chaining of interrupted and called tasks. The processor
/// sets this flag on calls to a task initiated with a CALL
/// instruction, an interrupt, or an exception. It examines and modifies
/// this flag on returns from a task initiated with the IRET
/// instruction. The flag can be explicitly set or cleared
/// with the POPF/POPFD instructions; however, changing to the state of
/// this flag can generate unexpected exceptions in application
/// programs.
///
/// See also: Section 7.4, "Task Linking."
const NT = 1 << 14;
/// Resume
///
/// Controls the processor’s response to instruction-breakpoint
/// conditions. When set, this flag temporarily disables debug
/// exceptions (#DB) from being generated for instruction breakpoints
/// (although other exception conditions can cause an exception to be
/// generated). When clear, instruction breakpoints will
/// generate debug exceptions.
///
/// The primary function of the RF flag is to allow the restarting of an
/// instruction following a debug exception that was caused by
/// an instruction breakpoint condition. Here, debug software must set
/// this flag in the EFLAGS image on the stack just prior to
/// returning to the interrupted program with IRETD (to prevent the
/// instruction breakpoint from causing another debug exception). The
/// processor then automatically clears this flag after the
/// instruction returned to has been successfully executed, enabling
/// instruction breakpoint faults again.
///
/// See also: Section 17.3.1.1, "Instruction-Breakpoint Exception
/// Condition."
const RF = 1 << 16;
/// Virtual-8086 mode
///
/// Set to enable virtual-8086 mode; clear to return to protected mode.
///
/// See also: Section 20.2.1, "Enabling Virtual-8086 Mode."
const VM = 1 << 17;
/// Alignment check or access control
///
/// If the AM bit is set in the CR0 register, alignment
/// checking of user-mode data accesses is enabled if and only if this flag is 1. An alignment-check exception
/// is generated when reference is made to an unaligned operand, such as a word at an odd byte address or a
/// doubleword at an address which is not an integral multiple of four. Alignment-check exceptions are generated only in user mode (privilege level 3). Memory references that default to privilege level 0, such as
/// segment descriptor loads, do not generate this exception even when caused by instructions executed in
/// user-mode.
///
/// The alignment-check exception can be used to check alignment of data. This is useful when exchanging
/// data with processors which require all data to be aligned. The alignment-check exception can also be used
/// by interpreters to flag some pointers as special by misaligning the pointer. This eliminates overhead of
/// checking each pointer and only handles the special pointer when used.
///
/// If the SMAP bit is set in the CR4 register, explicit supervisor-mode data accesses to user-mode pages are
/// allowed if and only if this bit is 1. See Section 4.6, "Access Rights."
const AC = 1 << 18;
/// Virtual Interrupt
///
/// Contains a virtual image of the IF flag. This flag is used in conjunction with
/// the VIP flag. The processor only recognizes the VIF flag when either the VME flag or the PVI flag in control
/// register CR4 is set and the IOPL is less than 3. (The VME flag enables the virtual-8086 mode extensions;
/// the PVI flag enables the protected-mode virtual interrupts.)
///
/// See also: Section 20.3.3.5, "Method 6: Software Interrupt Handling," and Section 20.4, "Protected-Mode
/// Virtual Interrupts."
const VIF = 1 << 19;
/// Virtual interrupt pending
///
/// Set by software to indicate that an interrupt is pending; cleared to
/// indicate that no interrupt is pending. This flag is used in conjunction with the VIF flag. The processor reads
/// this flag but never modifies it. The processor only recognizes the VIP flag when either the VME flag or the
/// PVI flag in control register CR4 is set and the IOPL is less than 3. The VME flag enables the virtual-8086
/// mode extensions; the PVI flag enables the protected-mode virtual interrupts.
///
/// See Section 20.3.3.5, "Method 6: Software Interrupt Handling," and Section 20.4, "Protected-Mode Virtual
/// Interrupts."
const VIP = 1 << 20;
/// Identification.
///
/// The ability of a program or procedure to set or clear this flag
/// indicates support for the CPUID instruction.
const ID = 1 << 21;
}
}
impl Rflags {
/// Read the current value.
#[inline(always)]
pub fn read() -> Self {
let ret: u64;
unsafe {
asm!(
"pushf",
"pop {0}",
lateout(reg) ret,
);
Self::from_bits_truncate(ret)
}
}
}
bitflags::bitflags! {
/// Cr0 Register.
#[repr(transparent)]
pub struct Cr0: u64 {
/// Protected mode enable.
const PE = 1 << 0;
/// Monitor co-processor.
const MP = 1 << 1;
/// Emulation.
const EM = 1 << 2;
/// Task switched.
const TS = 1 << 3;
/// Extension type.
const ET = 1 << 4;
/// Numeric error.
const NE = 1 << 5;
/// Write protect.
const WP = 1 << 16;
/// Alignment mask.
const AM = 1 << 18;
/// Not-write through.
const NW = 1 << 29;
/// Cache disable.
const CD = 1 << 30;
/// Paging.
const PG = 1 << 31;
}
}
impl Cr0 {
/// Read the current value.
#[inline(always)]
pub fn current() -> Self {
let ret: u64;
unsafe {
asm!("mov {}, cr0", lateout(reg) ret, options(nomem, nostack));
Self::from_bits_unchecked(ret)
}
}
/// Read the current value.
///
/// # Safety
/// Write to system register is unsafe.
#[inline(always)]
pub unsafe fn apply(self) {
asm!("mov cr0, {}", in(reg) self.bits(), options(nomem, nostack));
}
}
bitflags::bitflags! {
/// Cr4 Register.
#[repr(transparent)]
pub struct Cr4: u64 {
/// Virtual 8086 mode extensions.
const VME = 1 << 0;
/// Protected mode virtual interrupts.
const PVI = 1 << 1;
/// Time stamp disable.
const TSD = 1 << 2;
/// Debugging extensions.
const DE = 1 << 3;
/// Page size extension.
const PSE = 1 << 4;
/// Physical address extension.
const PAE = 1 << 5;
/// Machine check exception.
const MCE = 1 << 6;
/// Page global enable.
const PGE = 1 << 7;
/// Performance monitoring counter enable.
const PCE = 1 << 8;
/// Os support for fxsave and fxrstor instructions.
const OSFXSR = 1 << 9;
/// Os support for unmasked simd floating point exceptions.
const OSXMMEXCPT = 1 << 10;
/// User mode instruction prevention (#GP on SGDT, SIDT, SLDT, SMSW, and STR instructions when CPL > 0).
const UMIP = 1 << 11;
/// Virtual machine extensions enable.
const VMXE = 1 << 13;
/// Safer mode extensions enable.
const SMXE = 1 << 14;
/// Pcid enable.
const PCIDE = 1 << 17;
/// Xsave and processor extended states enable.
const OSXSAVE = 1 << 18;
/// Supervisor mode executions protection enable.
const SMEP = 1 << 20;
/// Supervisor mode access protection enable.
const SMAP = 1 << 21;
/// Protection keys for user-mode pages enable.
const PKE = 1 << 22;
/// Control-flow-enforcement enable.
const CET = 1 << 23;
/// Protection keys for supervisor-mode pages enable.
const PKS = 1 << 24;
}
}
impl Cr4 {
/// Read the current value.
#[inline(always)]
pub fn current() -> Self {
let ret: u64;
unsafe {
asm!("mov {}, cr4", lateout(reg) ret, options(nomem, nostack));
Self::from_bits_unchecked(ret)
}
}
/// Read the current value.
///
/// # Safety
/// Write to system register is unsafe.
#[inline(always)]
pub unsafe fn apply(self) {
asm!("mov cr4, {}", in(reg) self.bits(), options(nomem, nostack));
}
}